zoukankan      html  css  js  c++  java
  • HDU 1956 POJ 1637 Sightseeing tour

    混合图的欧拉回路判定方法:

    1.首先判断基图是否连通,不连通的话表示不可能,否则进入下一步。

    2.对于无向边,随便确定一个方向

    3.确定好了之后,整张图就变成了有向图,计算每个节点的入度与出度

    4.如果有一个节点的入度—出度是奇数,那么表示不可能,否则进入下一步

    5.建立网络,新增一个原点s,和汇点t,然后建立网络

    for(i=1; i<=M; i++)
        if(ff[i]==0)//如果是有向边
             AddEdge(u[i],v[i],1);
    for(i=1; i<=N; i++)
    {
        if(Ru[i]>Chu[i])
            AddEdge(i,t,(Ru[i]-Chu[i])/2);
        else
             AddEdge(s,i,(Chu[i]++-Ru[i])/2);
    }            

    6.计算网络最大流。

    7.如果从S引出的边有流量的都是满流,那么表示存在,否则不存在。

    8.把网络流中与S,T不关联的边找到,这些边中如果有流量等于1的边,那么将这些边反向,最终得到了一张欧拉图。

    AC代码(网络最大流用了Dinic连续最短增广路算法):

    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<queue>
    #include<algorithm>
    using namespace std;
    
    
    const int maxn=2000+10;
    const int INF=0x7FFFFFFF;
    
    struct Edge
    {
        int from,to,cap,flow;
    };
    vector<Edge>edges;
    vector<int>G[maxn];
    bool vis[maxn];
    int d[maxn];
    int cur[maxn];
    int Ru[maxn];
    int Chu[maxn];
    int u[maxn],v[maxn],ff[maxn];
    int father[maxn];
    int m,s,t,tot;
    int N,M;
    
    //求出层次网络
    bool BFS()
    {
        memset(vis,0,sizeof(vis));
        queue<int>Q;
        Q.push(s);
        d[s]=0;
        vis[s]=1;
        while(!Q.empty())
        {
            int x=Q.front();
            Q.pop();
            for(int i=0; i<G[x].size(); i++)
            {
                Edge& e=edges[G[x][i]];
                if(!vis[e.to]&&e.cap>e.flow)
                {
                    vis[e.to]=1;
                    d[e.to]=d[x]+1;
                    Q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    
    
    //加边
    void AddEdge(int from,int to,int cap)
    {
        Edge r;
        r.from=from;
        r.to=to;
        r.cap=cap;
        r.flow=0;
        edges.push_back(r);
        Edge d;
        d.from=to;
        d.to=from;
        d.cap=0;
        d.flow=0;
        edges.push_back(d);
        m=edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }
    
    //每个阶段来一次DFS增广
    int DFS(int x,int a)
    {
        if(x==t||a==0) return a;
        int flow=0,f;
        for(int i=cur[x]; i<G[x].size(); i++)
        {
            Edge& e=edges[G[x][i]];
            if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0)
            {
                e.flow+=f;
                edges[G[x][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if(a==0) break;
            }
        }
        return flow;
    }
    
    //多个阶段,多次建立层次网络。
    int Maxflow(int ss,int tt)
    {
        int flow=0;
        while(BFS())
        {
            memset(cur,0,sizeof(cur));
            flow+=DFS(ss,INF);
        }
        return flow;
    }
    
    int Find(int x)
    {
        if(x!=father[x]) father[x]=Find(father[x]);
        return father[x];
    }
    
    int main()
    {
        int T,flag,i;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&N,&M);
            edges.clear();
            for(i=0; i<maxn; i++) G[i].clear();
            flag=1;
            s=0,t=N+1;//设置超级原点和超级汇点
            memset(Ru,0,sizeof(Ru));
            memset(Chu,0,sizeof(Chu));
            for(i=0;i<=N;i++) father[i]=i;
            tot=N;
            for(i=1; i<=M; i++)
            {
                scanf("%d%d%d",&u[i],&v[i],&ff[i]);
                int fx=Find(u[i]);
                int fy=Find(v[i]);
                if(fx!=fy)
                {
                    father[fx]=fy;
                    tot--;
                }
                Ru[v[i]]++;
                Chu[u[i]]++;
            }
            if(tot!=1) flag=0;
            if(flag)
            {
                for(i=1; i<=N; i++)
                    if(abs(Ru[i]-Chu[i])%2==1)
                    {
                        flag=0;
                        break;
                    }
            }
            if(flag)
            {
                for(i=1; i<=M; i++)
                    if(ff[i]==0)//如果是有向边
                        AddEdge(u[i],v[i],1);
                for(i=1; i<=N; i++)
                {
                    if(Ru[i]>Chu[i])
                        AddEdge(i,t,(Ru[i]-Chu[i])/2);
                    else
                        AddEdge(s,i,(Chu[i]++-Ru[i])/2);
                }
                Maxflow(s,t);
                for(i=0; i<edges.size(); i++)
                    if(edges[i].from==s&&edges[i].cap!=edges[i].flow)
                    {
                        flag=0;
                        break;
                    }
            }
            if(flag) printf("possible
    ");
            else printf("impossible
    ");
        }
        return 0;
    }
  • 相关阅读:
    了解 NoSQL 的必读资料
    关于什么时候用assert(断言)的思考
    这次见到了一些大侠
    NetBeans 时事通讯(刊号 # 87 Jan 12, 2010)
    动态链接库dll,静态链接库lib, 导入库lib
    新女性十得 写得了代码,查得出异常
    记录系统乱谈
    新女性十得 写得了代码,查得出异常
    fullpage.js禁止滚动
    RunningMapReduceExampleTFIDF hadoopclusternet This document describes how to run the TFIDF MapReduce example against ascii books. This project is for those who wants to experiment hadoop as a skunkworks in a small cluster (110 nodes) Google Pro
  • 原文地址:https://www.cnblogs.com/zufezzt/p/4673490.html
Copyright © 2011-2022 走看看