POJ 1637 - Sightseeing tour 判断混合图是否是欧拉回路(最大流)

来源:互联网 发布:小型图书馆源码 编辑:程序博客网 时间:2024/04/18 19:17

                  题意:

                            给一个图..有些边是有向的...有些边是无向的...问能否有一条路径..从某点出发..又回到该点..并且所有的边经过exaclty一次...

                  题解

                            这题就是判断混合图欧拉回路的裸题....解法是先任意将每个无向边定向..然后来调整...看能否满足有向图欧拉回路的条件(所有点入度=出度)...

                            具体的...在把所有无向边定向后..先看每个点入度和出度之差..若有一个点其为奇数..则说明impossible..因为就算后面调整..调整一个边的方向..两头的点入度出度之差的变化必然为偶数...所以若为奇数..无论如何调整都无法使其变成0...然后就要看能否经过调整变成一个欧拉图了...参考了别人的建图...所有无向边定向后起点到终点连一条容量为1的边...然后设一个超级源点,向所有所有出度多了点做边..容量为其多了的边数/2(因为每次改变边..出度-1,入度+1..之差变化2)...所有入度多了的点往一个超级汇点做边..容量为其多了的边数/2...跑最大流...然后看和超级源点连得边是否容量都空了..与超级汇点连得边是否容量都空了...如果都空了..则说明是可以构造成欧拉图的..

                             构边理由..1、是无向边两点间容量为1的边..代表这个无向边至多改变方向一次...

                                             2、超级源点和超级汇点的边代表连着的这些点要让入度出度之差为0...所以要从左侧出度多的..调整到右侧入度多的..如果这些边都为0..就说明了可以让所有的点入度=出度...

                              总结此类模型的特点: 整个对象可以分成两个集合..并且其中一个集合是要从另一个集合中获取资源..而另一个集合也必须要释放资源...使得两个集合的资源都正好...


Program:

#include<iostream>#include<algorithm>#include<stdio.h>#include<string.h>#include<math.h>#include<queue>#define MAXN 3005#define MAXM 500005#define oo 1000000007#define ll long longusing namespace std;int d[MAXN];struct Dinic{      struct node       {             int x,y,c,next;      }line[MAXM];         int Lnum,_next[MAXN],dis[MAXN];      void initial(int n)       {             for (int i=0;i<=n;i++) _next[i]=-1;             Lnum=-1;      }       void addline(int x,int y,int c)      {             line[++Lnum].next=_next[x],_next[x]=Lnum;             line[Lnum].x=x,line[Lnum].y=y,line[Lnum].c=c;             line[++Lnum].next=_next[y],_next[y]=Lnum;             line[Lnum].x=y,line[Lnum].y=x,line[Lnum].c=0;                   }      bool BFS(int s,int e)      {              queue<int> Q;             while (!Q.empty()) Q.pop();             memset(dis,0,sizeof(dis));             dis[s]=1;             Q.push(s);             while (!Q.empty())             {                   int h,k;                   h=Q.front(),Q.pop();                   if (h==e) return dis[e];                   for (k=_next[h];k!=-1;k=line[k].next)                      if (line[k].c && !dis[line[k].y])                         dis[line[k].y]=dis[h]+1,Q.push(line[k].y);                              }              return false;      }      int dfs(int x,int flow,int e)        {                  if (x==e) return flow;                int temp,cost=0;               for (int k=_next[x];k!=-1;k=line[k].next)               if (line[k].c && dis[line[k].y]==dis[x]+1)               {                      temp=dfs(line[k].y,min(flow-cost,line[k].c),e);                       if (temp)                      {                             line[k].c-=temp,line[k^1].c+=temp;                             cost+=temp;                             if (flow==cost) return cost;                      }else dis[line[k].y]=-1;               }               return cost;        }        int MaxFlow(int s,int e)      {             int MaxFlow=0;             while (BFS(s,e))                 MaxFlow+=dfs(s,oo,e);              return MaxFlow;      }}T;bool legal(int n){       int i;       for (i=1;i<=n;i++)           if (d[i]%2) return false;       return true;}int main()  {                 int n,m,cases,x,y,c,s,e,sum;        scanf("%d",&cases);       while (cases--)         {                 scanf("%d%d",&n,&m);               s=n+1,e=s+1,sum=0;               T.initial(e);                memset(d,0,sizeof(d));               while (m--)               {                      scanf("%d%d%d",&x,&y,&c);                      d[x]--,d[y]++;                      if (!c) T.addline(x,y,1);               }               if (!legal(n)) { printf("impossible\n"); continue; }               for (int i=1;i<=n;i++)               {                       d[i]/=2;                      if (d[i]<0) T.addline(s,i,-d[i]);                      if (d[i]>0) T.addline(i,e,d[i]);                      sum+=abs(d[i]);               }               sum>>=1;               if (T.MaxFlow(s,e)==sum) printf("possible\n");                                  else  printf("impossible\n");       }         return 0;  }