2016计蒜之道复赛 菜鸟物流的运输网络

来源:互联网 发布:淘宝做复制店会封店吗 编辑:程序博客网 时间:2024/05/01 02:15

题目链接:点这里!!!


题意:给你n(3<=n<=100)个点m(m<=n*(n-1)/2)t条无向边,让你找一条a->b的一条路线,且必须经过mid点,每个点最多走一遍,输出这条路径。


好久没写网络流的题了,遇到这个题就有点傻比了,比赛的时候没做出来,赛后补了一下知识点,就差不多啦!!


题解:

每个点最多只能经过一次,我们可以把i点拆成i和i+n两个点,且在i和i+n两个点间连一条容量为1(i=mid的时候容量为2)的有向边,假设x与y边相连,则建一条x+n->y容量为1的边。

然后我们设超级源为s,超级汇为t,建一条s->mid为2容量的边,a->t,b->t容量为1的边,题目就可以简化成mid到a,b两点路径不存在交叉。然后跑一边最大流。

我们得到了跑完最大流的图,我们知道如果边有经过的话,那么他是有流量的。我们可以先在图上dfs下,从s到t然后将有流量的边标记下或者减一下,然后再从s到t,就得到了我们想要的答案。


代码:

#include<cstdio>#include<cstring>#include<iostream>#include<sstream>#include<algorithm>#include<vector>#include<bitset>#include<set>#include<queue>#include<stack>#include<map>#include<cstdlib>#include<cmath>#define LL long long#define pb push_back#define pa pair<int,int>#define clr(a,b) memset(a,b,sizeof(a))#define lson lr<<1,l,mid#define rson lr<<1|1,mid+1,r#define bug(x) printf("%d++++++++++++++++++++%d\n",x,x)#define key_value ch[ch[root][1]][0]#pragma comment(linker, "/STACK:102400000000,102400000000")const LL  MOD = 1000000007;const int N = 100+15;const int maxn = 8e3+15;const int letter = 130;const int INF = 1000000;const double pi=acos(-1.0);const double eps=1e-10;using namespace std;inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}int n,m,head[2*N],tot;int a,b,mid;int dis[2*N],cur[2*N],vis[N*2];int p[2*N];vector<int>vp;queue<int>q;struct edges{    int to,next,ca,fl;}e[8*N*N];void addedges(int u,int v,int val){    e[tot].to=v,e[tot].ca=val,e[tot].fl=0,e[tot].next=head[u],head[u]=tot++;    e[tot].to=u,e[tot].ca=0,  e[tot].fl=0,e[tot].next=head[v],head[v]=tot++;}bool bfs(int s,int t){    int x,to;    clr(dis,-1);    while(!q.empty()) q.pop();    dis[s]=0;    q.push(s);    while(!q.empty()){        x=q.front(),q.pop();        for(int i=head[x];i!=-1;i=e[i].next){            to=e[i].to;            if(dis[to]<0&&e[i].ca-e[i].fl>0){                dis[to]=dis[x]+1;                q.push(to);            }        }    }    return dis[t]!=-1;}int dfs(int t,int x,int f){    if(x==t) return f;    int w,used=0;    for(int i=cur[x];i!=-1;i=e[i].next){        int to=e[i].to;        if(dis[to]==dis[x]+1){            w=f-used;            w=dfs(t,to,min(w,e[i].ca-e[i].fl));            e[i].fl+=w;            e[i^1].fl-=w;            if(e[i].ca-e[i].fl>0) cur[x]=i;            used+=w;            if(used==f) return f;        }    }    if(!used) dis[x]=-1;    return used;}int maxflow(int s,int t){    int flow=0;    while(bfs(s,t)){        for(int i=0;i<=t;i++)cur[i]=head[i];        flow+=dfs(t,s,INF);    }    return flow;}void pp(int x){    if(x<=n&&x!=0) vp.pb(x);    if(x==2*n+2) return;    for(int i=head[x];i!=-1;i=e[i].next){        int to=e[i].to;        if(e[i].ca&&e[i].fl){            e[i].fl--;            pp(to);            return;        }    }}void solve(int s,int t){    vp.clear();    pp(s);    if(vp[vp.size()-1]==a){        for(int i=vp.size()-1;i>=0;i--){            if(i==vp.size()-1) printf("%d",vp[i]);            else printf(" %d",vp[i]);        }        vp.clear();        pp(s);        for(int i=1;i<vp.size();i++) printf(" %d",vp[i]);        puts("");    }    else {        pp(s);        reverse(vp.begin(),vp.end());        int flag=0;        for(int i=0;i<vp.size();i++){            if(vp[i]==b){                flag=i;                break;            }            else {                if(i==0) printf("%d",vp[i]);                else printf(" %d",vp[i]);            }        }        for(int i=vp.size()-2;i>=flag;i--){            printf(" %d",vp[i]);        }        puts("");    }}int main(){    int tc;    scanf("%d",&tc);    while(tc--){        tot=0,clr(head,-1),clr(p,0);        scanf("%d%d",&n,&m);        scanf("%d%d%d",&a,&b,&mid);        int s=0,t=2*n+2;        for(int i=1;i<=n;i++){            if(i==a||i==b){                addedges(i,i+n,1);                addedges(i+n,t,1);            }            else if(i==mid){                addedges(s,i,2);                addedges(i,i+n,2);            }            else {                addedges(i,i+n,1);            }        }        int x,y;        for(int i=0;i<m;i++){            scanf("%d%d",&x,&y);            addedges(x+n,y,1);            addedges(y+n,x,1);        }        maxflow(s,t);        solve(s,t);    }    return 0;}


0 0