码迷,mamicode.com
首页 > 其他好文 > 详细

hdu5294Tricks Device 最大流之最小割

时间:2015-08-16 19:56:43      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:

//给一个无向图,
//一个人从起点到走到终点只走最短路
//问最少需要删除多少边使得其不能从起点走到终点
//问最多删除多少点使得其能走到终点
//先求出所有在最短路上的边,对这些边重建图
//将其权值改为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;
    }
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

hdu5294Tricks Device 最大流之最小割

标签:

原文地址:http://blog.csdn.net/cq_pf/article/details/47704221

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!