2017模拟赛 deep dark fantasy(网络流)

来源:互联网 发布:公司邮箱域名是什么 编辑:程序博客网 时间:2024/06/05 09:12

题目

题目大意:给出m条有两个可选择终点的有向边与n个点,求当满足每个点的入度与出度相同时对于每个边的选择情况

题解

考虑到入度和出度相等所以从源点向每个点连一条容量为1的边再根据加边的连接情况依次向后面的点连容量为一的点,最后在从每个点向终点连一条容量为出度的边。

代码

#include<cstdio>#include<algorithm>#include<cmath>#include<iostream>#include<cstring>#include<queue>#include<stdio.h>using namespace std;#define maxn 200005#define inf 1e9int cnt=1;int n,m;int Next[maxn],End[maxn],Last[maxn],Len[maxn];int dis[maxn],Cnt[maxn];int chu[maxn];int edge[maxn][3],mar[maxn];void insert(int x,int y,int z){    Next[++cnt]=Last[x];    Last[x]=cnt;    End[cnt]=y;    Len[cnt]=z;}int dfs(int x,int flow){    if(x==n+m+1) return flow;    int i,temp,delta=0;    for(i=Last[x];i;i=Next[i]){        int en=End[i];        if(dis[x]==dis[en]+1&&Len[i]>0){            temp=dfs(en,min(Len[i],flow-delta));            Len[i]-=temp;            Len[i^1]+=temp;            delta+=temp;            if(dis[0]>=n+m+1||delta==flow) return delta;        }    }    Cnt[dis[x]]--;    if(Cnt[dis[x]]==0) dis[0]=n+m+1;    Cnt[++dis[x]]++;    return delta;}int main(){    int i,j,k;    scanf("%d%d",&n,&m);    for(i=1;i<=m;i++){        int a,b,c;        scanf("%d%d%d",&edge[i][0],&edge[i][1],&edge[i][2]);        chu[edge[i][0]]++;    }    for(i=1;i<=m;i++){        insert(0,i,1);        insert(i,0,0);    }    int Num=0;    for(i=1;i<=m;i++){        insert(i,edge[i][1]+m,1);        mar[++Num]=cnt;        insert(edge[i][1]+m,i,0);        insert(i,edge[i][2]+m,1);        mar[++Num]=cnt;        insert(edge[i][2]+m,i,0);     }    for(i=1;i<=n;i++){        if(!chu[i]) continue;        insert(i+m,n+m+1,chu[i]);        insert(n+m+1,i+m,0);    }    int temp;    while(dis[0]<=n+m+1) temp=dfs(0,inf);    for(i=1;i<=2*m;i+=2){        if(Len[mar[i]]) cout<<"1";        else cout<<"0";    } }
原创粉丝点击