hdu5294Tricks Device 最大流之最小割

来源:互联网 发布:家庭电路设计软件 编辑:程序博客网 时间:2024/05/18 02:01
//给一个无向图,//一个人从起点到走到终点只走最短路//问最少需要删除多少边使得其不能从起点走到终点//问最多删除多少点使得其能走到终点//先求出所有在最短路上的边,对这些边重建图//将其权值改为1,那么其最大流就是其最小割//刚开始没有考虑为无向图,坑了半天#include<cstdio>#include<cstring>#include<iostream>#include<queue>using namespace std ;const int maxn = 2010 ;const int maxm = 12e4+10 ;const int inf = 0x3f3f3f3f ;int head[maxn] , vis[maxn] ;int dis[maxn] ;int x[maxm] , y[maxm] , z[maxm] ;int sum[maxn] ;int len ;int nedge ;int n , m ;int st , en ;struct Edge{    int v , w ;    int next ;}edge[maxm<<1] ;void addedge(int u , int v ,int w){    edge[nedge].v = v;    edge[nedge].w = w ;    edge[nedge].next = head[u] ;    head[u] = nedge++ ;}int spfa(){    memset(vis , 0  ,sizeof(vis)) ;    for(int i = 1;i <= n;i++)    sum[i] = dis[i] = i == st ? 0 : inf ;    queue<int>que;    que.push(st) ; vis[st] = 1;    while(que.size())    {        int u = que.front();que.pop() ;        vis[u] = 0 ;        for(int i = head[u];i != -1 ;i = edge[i].next)        {            int v = edge[i].v ;            if(edge[i].w && dis[u] + edge[i].w < dis[v])            {                dis[v] = dis[u] + edge[i].w ;                if(!vis[v])                {                    vis[v] = 1 ;                    que.push(v) ;                }            }        }    }    return dis[en] ;}bool bfs(){    queue<int> que ;    memset(dis , -1 ,sizeof(dis)) ;    dis[st] = 0 ;    que.push(st) ;    while(que.size())    {        int u = que.front() ;        que.pop() ;        for(int i = head[u]; i != -1 ; i = edge[i].next)        {            int v = edge[i].v ;            if(edge[i].w > 0 && dis[v] < 0)            {                dis[v] = dis[u] + 1 ;                que.push(v) ;            }        }    }    if(dis[en] > 0)    return true ;    return false ;}int dfs(int x,int mx){    if(x==en)    return mx;    int i;    int ans=0;    int a;    for(i=head[x];i!=-1;i=edge[i].next)    {        int v=edge[i].v;        if(dis[v]==dis[x]+1&&edge[i].w>0&&(a=dfs(v,min(mx,edge[i].w))))        {            edge[i].w -= a;            edge[i^1].w += a;            ans += a;            mx -= a;            if(!mx)            break;        }    }    if(!ans)    dis[x] = -1;    return ans;}int main(){   // freopen("in.txt" , "r" , stdin) ;    while(~scanf("%d%d" , &n , &m))    {        memset(head , -1 , sizeof(head)) ;        nedge = 0 ;len = 0 ;        for(int i = 0;i < m;i++)        {            int u , v , w ;            scanf("%d%d%d" , &u , &v , &w) ;            addedge(u , v ,w) ;            addedge(v , u , w) ;            x[len] = u , y[len] = v ,z[len++] = w ;            x[len] = v , y[len] = u ,z[len++] = w ;        }        st = 1 , en = n;        int mi = spfa() ;        if(mi == inf)        {            puts("0 0");            continue ;        }        memset(head , -1 , sizeof(head)) ;        nedge = 0 ;        for(int i = 0;i < len ;i++)        if(dis[x[i]] + z[i] == dis[y[i]])        {            addedge(x[i] , y[i] , 1) ;            addedge(y[i] , x[i] , 0) ;        }        mi = spfa() ;        int ans = 0 ,res ;        while(bfs())          while(res = dfs(st , inf))            ans += res ;        cout<<ans<<" "<<m - mi<<endl;    }}

0 0