混合图偶拉回路的判定。

题意: 给出一张图,途中既有有向边又有无向边,现在想要判断这个图里边是否存在欧拉回路。

 

思路: 开始的时候我直接用求普通图的欧拉回路的方法求,如果求出的边的条数为m那么就存在,否则不存在。但是wa了。

如果存在欧拉回路,那么每个点的入度和出度相等。 我们要努力的做的是让每个点的出度和入度相等。

假设入度为in, 总度数为d,如果d为奇数, 那么可定不存在欧拉回路。 如果in>d/2也不存在欧拉回路。

我们努力做的就是构造d/2-in个入度, 这里我们用网络流。 对于每个无向边,我们缩成一个点,这个点向这条边两端的点有边,且流量为1, 源点到缩点也有边,流量为1. 途中原先的点向汇点的流量为d/2-in.如果这个图能满流,那么就存在欧拉回路。否则不存在。

 

AC代码:

View Code
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
const int N = 8010, INF = 1<<29;

struct EDGE
 {
     int u,  v, next, cap;
 }edge[N*4];

int f[N], in[N], d[N], cur[N], dis[N], pre[N], gap[N], n, m;
int num, head[N], cc;

void add(int u, int v, int w)
 {
     edge[num].u = u;
     edge[num].v = v;
     edge[num].cap = w;
     edge[num].next = head[u];
     head[u] = num++;
 }

int find(int u)
 {
     if(f[u] != u)
      f[u] = find(f[u]);
     return f[u];
 }

void unio(int u, int v)
 {
     int x = find(u), y =find(v);
     if(x < y) f[y] = x;
     else f[x] = y;
 }

bool init()
 {
     scanf("%d%d", &n, &m);

     int u, v, s, tp=n;
     cc = 0;
     num = 0;
     memset(head, -1, sizeof(head));
     for(int i=1; i<=n; i++)
      {
          in[i] = d[i] = 0;
          f[i] = i;
      }
     for(int i=1; i<=m; i++)
      {
          scanf("%d%d%d", &u, &v, &s);
          unio(u, v);
          d[u]++;
          d[v]++;
          if(s == 1)
           {
               in[v]++;
           }
          else
           {
               tp++;
               cc++;
               add(tp,u,1);
               add(u,tp,0);
               add(tp,v,1);
               add(v,tp,0);

               add(0,tp,1);
               add(tp,0,0);
           }
      }
    bool flag = 1;
    for(int i=1; i<=n; i++)
     {
         if(d[i]%2 || (in[i] > d[i]/2))
          {
              flag = 0;
              break;
          }
        /* if(i > 1)
          {
              if(f[i] != f[i-1])
               {
                   flag = 0;
                   break;
               }
          }*/
        add(i,tp+1,d[i]/2 - in[i]);
        add(tp+1, i, 0);
     }
    n = tp+1;
    if(!flag)
     {
         printf("impossible\n");
     }
    return flag;
 }

void solve(int s, int t)
 {
    memset(gap,0,sizeof(gap));
    memset(dis,0,sizeof(dis));
    int i;
    for(i=0;i<=t+1;i++)
    {
        cur[i] = head[i];
    }
    int top=s;
    gap[s]=t+1;
    int  maxflow=0,flow=INF;
    while(dis[s] < t+1)
    {
        for(i=cur[top];i != -1;i = edge[i].next)
        {
            if(edge[i].cap > 0 && dis[top] == dis[edge[i].v] + 1)
                break;
        }
        if(i != -1)
        {
            cur[top] = i;
            int v = edge[i].v;
            if(edge[i].cap < flow)
            {
                flow = edge[i].cap;
            }
            top = v;
            pre[v] = i;
            if(top == t)
            {
                maxflow += flow;
                while(top != s)
                {
                    edge[pre[top]].cap -= flow;
                    edge[pre[top]^1].cap += flow;
                    top = edge[pre[top]^1].v;
                }
                flow = INF;
            }
        }
        else
        {
            if(--gap[dis[top]] == 0)
            {
                break;
            }
            dis[top] = t+1;
            cur[top] = head[top];
            for(int j=head[top];j != -1;j=edge[j].next)
            {
                if(edge[j].cap > 0 && dis[edge[j].v] + 1 < dis[top])
                {
                    dis[top] = dis[edge[j].v] + 1;
                    cur[top] = j;
                }
            }
            gap[dis[top]]++;
            if(top != s)
            {
                top = edge[pre[top]^1].v;
            }
        }
    }

   // cout<<maxflow<<"           "<<cc<<endl;
    if(maxflow == cc)
     {
         printf("possible\n");
     }
    else
     {
         printf("impossible\n");
     }

 }

int main()
 {
     int t;
     scanf("%d", &t);
     while(t--)
      {
          if(init())
           {
               solve(0, n);
           }
      }
     return 0;
 }

 

 

 

 

 

 

posted @ 2012-09-29 19:29  Gu Feiyang  阅读(220)  评论(0)    收藏  举报