POJ 3204 Ikki's Story I - Road Reconstruction【关键割边】

题意: 给出有n 个节点的网络,和m条单向边,知道了每条边的容量,问哪些边满足增加该边的容量后,能使得从起点到终点的总流量增加(只能修改一条边!)。

分析:如果某条边是该关键边,首先满足该边一定能满流,其次要有从 s 到 t 经过该边的可行路径。

        先求最大流,找出割边,在正向网络上从 s 开始深搜,将遍历到点用v1[]标记,在反向网络上从 t 深搜,将遍历到的点用v2[]标记,

        如果某条边满足 e[i].cap=e[i].flow且v1[e[i].from]=1,e[e[i].to]=1,那么该边即为要求的关键边。

#include<stdio.h>
#include<string.h>
#define INF 0x1f1f1f1f
#define maxn 500
#define min(a,b)(a)<(b)?(a):(b)
#define max(a,b)(a)>(b)?(a):(b)
#define clr(x)memset(x,0,sizeof(x))
struct node
{
    int from,to,next,c,f;
}e[100000];
int tot;
int head[maxn];
void add(int s,int u,int wi)
{
    e[tot].from=s;
    e[tot].c=wi;
    e[tot].f=0;
    e[tot].to=u;
    e[tot].next=head[s];
    head[s]=tot++;

    e[tot].from=u;
    e[tot].c=0;
    e[tot].f=0;
    e[tot].to=s;
    e[tot].next=head[u];
    head[u]=tot++;
}
void EK(int s,int t,int n)
{
    int a[maxn];
    int p[maxn];
    int q[maxn];
    int i,u,k,front,rear;
    p[s]=-1;
    while(1)
    {
        clr(a);
        a[s]=INF;
        front=rear=0;
        q[rear++]=s;
        while(front<rear)
        {
            u=q[front++];
            for(i=head[u];i!=-1;i=e[i].next)
            {
                k=e[i].to;
                if(!a[k]&&e[i].f<e[i].c)
                {
                    p[k]=i;
                    q[rear++]=k;
                    a[k]=min(a[u],e[i].c-e[i].f);
                }
            }
        }
        if(a[t]==0)
            break;
        for(u=p[t];u!=-1;u=p[e[u].from])
        {
            
            e[u].f+=a[t];
            e[u^1].f-=a[t];
        }
    }
}
int v1[maxn],v2[maxn];
int g[maxn][maxn];
int n;
void dfs1(int r)
{
    int i;
    v1[r]=1;
    for(i=0;i<n;i++)
        if(!v1[i]&&g[r][i])
            dfs1(i);
}
void dfs2(int r)
{
    int i;
    v2[r]=1;
    for(i=0;i<n;i++)
        if(!v2[i]&&g[r][i])
            dfs2(i);
}
int main()
{
    int i,s,t,m,a,b,cc,res;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        tot=0;
        memset(head,-1,sizeof(head));
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&cc);
            add(a,b,cc);
        }
        s=0;
        t=n-1;
        clr(v1);
        clr(v2);
        EK(s,t,n);
        clr(g);
        for(i=0;i<tot;i+=2)
            if(e[i].c!=e[i].f)
                g[e[i].from][e[i].to]=1;
        dfs1(s);
        clr(g);
        for(i=0;i<tot;i+=2)
            if(e[i].c!=e[i].f)
                g[e[i].to][e[i].from]=1;
        dfs2(t);
        res=0;
        for(i=0;i<tot;i+=2)
        {
            if(v1[e[i].from]&&v2[e[i].to]&&e[i].f==e[i].c)
            res++;
        }
        printf("%d\n",res);
    }
    return 0;
}

 

posted @ 2012-08-24 23:10  'wind  阅读(194)  评论(0编辑  收藏  举报