【網絡流+最短路】 HDU 5294 Tricks Device

點擊打開鏈接

最短路求出到每個點的最小值以及邊數

枚舉下能到達終點的點的邊數num[i] 取個最小值 +1  然後減去m就是第二個輸出的數

對於原來的圖滿足最短路的邊建上一條邊跑網絡流 就得到最小割= =

因爲有重邊所以網絡流的邊的容量爲該邊最小權值的數量


#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <vector>
typedef long long  LL;
using namespace std;
const LL mod=1e9+7;
const int MAXN = 2010;//點數的最大值
const int MAXM = 160000;//邊數的最大值
const int INF = 0x3f3f3f3f;
struct Sap
{
    struct Edge
    {
        int to,next,cap,flow;
    } edge[MAXM]; //注意是MAXM
    int tol;
    int head[MAXN];
    int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];
    void init()
    {
        tol = 0;
        memset(head,-1,sizeof (head));
    }
//加邊,單向圖三個參數,雙向圖四個參數
    void addedge (int u,int v,int w,int rw=0)
    {
        edge[tol].to = v;
        edge[tol].cap = w;
        edge[tol].next = head[u];
        edge[tol].flow = 0;
        head[u] = tol++;
        edge[tol].to = u;
        edge[tol].cap = rw;
        edge[tol]. next = head[v];
        edge[tol].flow = 0;
        head[v]=tol++;
    }
//輸入參數:起點、終點、點的總數
//點的編號沒有影響,只要輸入點的總數
    int sap(int start,int end, int N)
    {
        memset(gap,0,sizeof(gap));
        memset(dep,0,sizeof(dep));
        memcpy(cur,head,sizeof(head));
        int u = start;
        pre[u] = -1;
        gap[0] = N;
        int ans = 0;
        int i;
        while(dep[start] < N)
        {
            if(u == end)
            {
                int Min = INF;
                for( i = pre[u]; i != -1; i = pre[edge[i^1]. to])
                {
                    if(Min > edge[i].cap - edge[i]. flow)
                        Min = edge[i].cap - edge[i].flow;
                }
                for( i = pre[u]; i != -1; i = pre[edge[i^1]. to])
                {
                    edge[i].flow += Min;
                    edge[i^1].flow -= Min;
                }
                u = start;
                ans += Min;
                continue;
            }
            bool flag =  false;
            int v;
            for( i = cur[u]; i != -1; i = edge[i].next)
            {
                v = edge[i]. to;
                if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u])
                {
                    flag =  true;
                    cur[u] = pre[v] = i;
                    break;
                }
            }
            if(flag)
            {
                u = v;
                continue;
            }
            int Min = N;
            for( i = head[u]; i !=  -1; i = edge[i]. next)
            {
                if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min)
                {
                    Min = dep[edge[i].to];
                    cur[u] = i;
                }
            }
            gap[dep[u]]--;
            if(!gap[dep[u]]) return ans;
            dep[u] = Min+1;
            gap[dep[u]]++;
            if(u != start) u = edge[pre[u]^1].to;
        }
        return ans;
    }
}wll;
bool vis[MAXN];
int pre[MAXN];
int cost[MAXN][MAXN],lowcost[MAXN],num[MAXN];
void Dijkstra(int n,int beg)
{
    for(int i=0; i<n; i++)
    {
        num[i]=0;
        lowcost[i]=INF;
        vis[i]=false;
        pre[i]=-1;
    }
    lowcost[beg]=0;
    for(int j=0; j<n; j++)
    {
        int k=-1;
        int Min=INF;
        for(int i=0; i<n; i++)
            if(!vis[i]&&lowcost[i]<Min)
            {
                Min=lowcost[i];
                k=i;
            }
        if(k==-1)break;
        vis[k]=true;
        for(int i=0; i<n; i++)
        {
            if(!vis[i]&&lowcost[k]+cost[k][i]<lowcost[i])
            {
                num[i]=num[k]+1;
                lowcost[i]=lowcost[k]+cost[k][i];
                pre[i]=k;
            }
            else if(i!=k&&lowcost[k]+cost[k][i]==lowcost[i]&&num[i]>num[k])
            {
                pre[i]=k;
            }
        }
    }
}
int val[MAXN][MAXN];
int main()
{
    int n,m,a,b,c;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
                cost[i][j]=INF;
            cost[i][i]=0;
        }
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            a--,b--;
            if(cost[a][b]>c)
            {
                cost[a][b]=cost[b][a]=c;
                val[a][b]=val[b][a]=1;
            }
            else if(cost[a][b]==c)
                val[a][b]++,val[b][a]++;
        }
        Dijkstra(n,0);
        int ans=INF;
        for(int i=0;i<n;i++)
            if(lowcost[n-1]==lowcost[i]+cost[i][n-1]&&num[i]+1<ans)
                ans=num[i]+1;
        wll.init();
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            {
                if(i==j) continue;
                if(cost[i][j]+lowcost[i]==lowcost[j])
                    wll.addedge(i,j,val[i][j]);
            }
        int first1=wll.sap(0,n-1,n);
        printf("%d %d\n",first1,m-ans);
    }
    return 0;
}
/*
3 5
1 2 1
1 2 1
1 2 2
2 3 1
2 3 1
*/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章