POJ1637 Sightseeing tour 网络流

来源:互联网 发布:ubuntu必装软件 编辑:程序博客网 时间:2024/05/18 03:13

        题目中既有有向边又有无向边,故不能直接当作普通的欧拉回路做。

        首先将无向边都随意选一个方向,并建立一条容量为1的边。然后算各点入度和出度,设一个源点s和汇点t,如果某点出度和入度的差u为奇数,则无欧拉回路;如果u大于0,则从s连一条有向边到该点,容量为u/2;否则从该点连一条有向边到t,容量为-u/2。然后求最大流。如果满流就存在欧拉回路,否则不存在。

#include<cstdio>#include<cstring>const int MAXN=210;const int MAXM=3010;const int INF=0x3f3f3f3f;int in[210],out[210];struct Node{    int from,to,next;    int cap;}edge[MAXM];int tol;int head[MAXN];int dep[MAXN];int gap[MAXN];int n;void init(){    tol=0;    memset(head,-1,sizeof(head));}void addedge(int u,int v,int w){    edge[tol].from=u;    edge[tol].to=v;    edge[tol].cap=w;    edge[tol].next=head[u];    head[u]=tol++;    edge[tol].from=v;    edge[tol].to=u;    edge[tol].cap=0;    edge[tol].next=head[v];    head[v]=tol++;}void BFS(int start,int end){    memset(dep,-1,sizeof(dep));    memset(gap,0,sizeof(gap));    gap[0]=1;    int que[MAXN];    int front,rear;    front=rear=0;    dep[end]=0;    que[rear++]=end;    while(front!=rear)    {        int u=que[front++];        if(front==MAXN)front=0;        for(int i=head[u];i!=-1;i=edge[i].next)        {            int v=edge[i].to;            if(dep[v]!=-1)continue;            que[rear++]=v;            if(rear==MAXN)rear=0;            dep[v]=dep[u]+1;            ++gap[dep[v]];        }    }}int SAP(int start,int end){    int res=0;    BFS(start,end);    int cur[MAXN];    int S[MAXN];    int top=0;    memcpy(cur,head,sizeof(head));    int u=start;    int i;    while(dep[start]<n)    {        if(u==end)        {            int temp=INF;            int inser;            for(i=0;i<top;i++)               if(temp>edge[S[i]].cap)               {                   temp=edge[S[i]].cap;                   inser=i;               }            for(i=0;i<top;i++)            {                edge[S[i]].cap-=temp;                edge[S[i]^1].cap+=temp;            }            res+=temp;            top=inser;            u=edge[S[top]].from;        }        if(u!=end&&gap[dep[u]-1]==0)          break;        for(i=cur[u];i!=-1;i=edge[i].next)           if(edge[i].cap!=0&&dep[u]==dep[edge[i].to]+1)             break;        if(i!=-1)        {            cur[u]=i;            S[top++]=i;            u=edge[i].to;        }        else        {            int min=n;            for(i=head[u];i!=-1;i=edge[i].next)            {                if(edge[i].cap==0)continue;                if(min>dep[edge[i].to])                {                    min=dep[edge[i].to];                    cur[u]=i;                }            }            --gap[dep[u]];            dep[u]=min+1;            ++gap[dep[u]];            if(u!=start)u=edge[S[--top]].from;        }    }    return res;}int main(){     //freopen("1.in","r",stdin);     int m,t,a,b,d;bool flag;     scanf("%d",&t);     while(t--)     {           scanf("%d%d",&n,&m);           init();           memset(in,0,sizeof(in));           memset(out,0,sizeof(out));           while(m--)           {                        scanf("%d%d%d",&a,&b,&d);                        in[b]++,out[a]++;                        if(!d)addedge(a,b,1);           }           bool flag=0;int sum=0;           for(int i=1;i<=n;i++)           {                   int u=out[i]-in[i];                   if(u%2==0)                   {                            if(u>0)addedge(0,i,u/2),sum+=u/2;                            else addedge(i,n+1,-u/2);                   }                   else flag=1;           }           n+=2;           if(SAP(0,n-1)!=sum)flag=1;           if(flag)printf("impossible\n");           else printf("possible\n");     }}


0 0