zoukankan      html  css  js  c++  java
  • 混合边的欧拉路径——poj1637 最大流

    http://poj.org/problem?id=1637

    题意:混合图欧拉回路

    一开始想到是否可以用欧拉回路做,可是一想a->b ,a<->b可以同时并且多次存在时,不可行
     

    构图:有向边忽略,无向边任意定向。统计每个点的出入度(有向边当无向边)。

    对于任意一个点,若有出入度之差为奇数则不可能存在欧拉路。

    记|出度-入度|=K。

    对于出度大于入度的点从S向I连容量为K/2的边,对于出度小于入度的点从I向T连容量为K/2的边。

    原来的无向边,任意定向,从X向Y连容量1的边。

    求最大流,判每条从S流出的边的流量和all是否等于最大流,是则存在欧拉路否则不存在。

    注意点:会有重边出现!而且重边也要走的

    View Code
    #include<stdio.h>
    #include<string.h>
    const int MAXN=309;
    const int inf=1000000000;

    int map[MAXN][MAXN];
    int doub[MAXN][MAXN];
    int du[MAXN];

    int max_flow(int n,int mat[][MAXN],int source,int sink)
    {
    int v[MAXN],c[MAXN],p[MAXN],ret=0,i,j;
    for(;;){
    for(i=0;i<n;i++)
    v[i]=c[i]=0;
    for(c[source]=inf;;){
    for(j=-1,i=0;i<n;i++)
    if(!v[i]&&c[i]&&(j==-1||c[i]>c[j]))
    j=i;
    if(j<0)return ret;
    if(j==sink)break;
    for(v[j]=1,i=0;i<n;i++)
    if(mat[j][i]>c[i]&&c[j]>c[i])
    c[i]=mat[j][i]<c[j]?mat[j][i]:c[j],p[i]=j;
    }
    for(ret+=j=c[i=sink];i!=source;i=p[i])
    mat[p[i]][i]-=j,mat[i][p[i]]+=j;
    }
    return ret;
    }

    int main()
    {
    int t;
    scanf("%d",&t);
    while(t--)
    {
    int n,m;
    memset(map,0,sizeof(map));
    memset(doub,0,sizeof(doub));
    memset(du,0,sizeof(doub));

    scanf("%d%d",&n,&m);
    int i,j,a,b,c;
    for(i=1;i<=m;i++)
    {
    scanf("%d%d%d",&a,&b,&c);
    map[a][b]++;
    doub[a][b]+=c^1;//注意无向边的容量作为1加到容量网络
    du[a]++;//会有重边出现!
    du[b]--;
    }

    int ok=1;
    for(i=1;i<=n;i++)
    {
    if(du[i]%2!=0)
    {
    ok=0;
    break;
    }
    }
    if(ok==0)
    {
    printf("impossible\n");
    continue;
    }

    int all=0;
    for(i=1;i<=n;i++)
    {
    if(du[i]>0)
    {
    doub[0][i]=du[i]/2;
    all+=du[i]/2;
    }
    else if(du[i]<0)
    {
    doub[i][n+1]=-du[i]/2;
    }
    }

    if(max_flow(n+2,doub,0,n+1)==all)
    {
    printf("possible\n");
    }
    else
    printf("impossible\n");
    }

    return 0;
    }


    一个速度比较快的代码

    View Code
    #include <queue>
    #include <stack>
    #include <math.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <iostream>
    #include <limits.h>
    #include <string.h>
    #include <algorithm>
    #define MAX 205
    using namespace std;
    int pre[MAX],n;
    int ind[MAX],outd[MAX];
    int lev[MAX];

    int min(int a,int b)
    {
    if(a<b)return a;
    else return b;
    }

    typedef struct MAP{
    int cap,to;
    int next;
    }MAP;
    MAP node[3000];
    int head[MAX];
    int cou;
    void init()
    {
    cou = 2;
    memset(node,'/0',sizeof(node));
    memset(head,-1,sizeof(head));
    memset(ind,0,sizeof(ind));
    memset(outd,0,sizeof(outd));
    for(int i=1; i<=n; i++)
    pre[i] = i;
    }
    int find(int x)
    {
    while( x != pre[x] )
    x = pre[x];
    return x;
    }
    void Union(int x,int y)
    {
    int a = find(x);
    int b = find(y);
    if( a == b )
    return ;
    int p = min(a,b);
    pre[a] = pre[b] = pre[x] = pre[y] = p;
    }
    int check()
    {
    for(int i=1; i<=n; i++)
    if( find(i) != 1 )
    return 0;
    return 1;
    }
    void Add(int u,int v,int cap)
    {
    node[cou].to = v;
    node[cou].cap = cap;
    node[cou].next = head[u];
    head[u] = cou++;

    node[cou].to = u;
    node[cou].cap = 0;
    node[cou].next = head[v];
    head[v] = cou++;
    }
    queue<int> q;
    int BFS(int s,int t)
    {
    int p,u,v,cap;
    memset(lev,-1,sizeof(lev));
    q.push(s);
    lev[s] = 0;
    while( !q.empty() )
    {
    u = q.front();
    q.pop();
    p = head[u];
    while( p != -1 )
    {
    v = node[p].to;
    cap = node[p].cap;
    if( cap > 0 && lev[v] == -1 )
    {
    lev[v] = lev[u] + 1;
    q.push(v);
    }
    p = node[p].next;
    }
    }
    return lev[t] != -1;
    }
    int Dinic(int k,int sum,int s,int t)
    {
    int i,a,os;
    if( k == t )
    return sum;
    os = sum;
    int p = head[k];
    while( p != -1 && sum )
    {
    int to = node[p].to;
    int cap = node[p].cap;
    if( lev[to] == lev[k] + 1 && cap > 0 )
    {
    a = Dinic(to,min(sum,cap),s,t);
    node[p^1].cap += a;
    node[p].cap -= a;
    sum -= a;
    }
    p = node[p].next;
    }
    return os - sum;
    }
    int main()
    {
    int m,from,to,s;
    int ncases;
    scanf("%d",&ncases);
    while( ncases-- )
    {
    scanf("%d%d",&n,&m);
    init();
    while( m-- )
    {
    scanf("%d%d%d",&from,&to,&s);
    if( from == to )
    continue;
    ind[to]++;
    outd[from]++;
    Union(from,to);
    if( s != 1 )
    Add(from,to,1);
    }
    if( !check() )
    {
    printf("impossible/n");
    continue;
    }
    int flag = 1;
    int sum = 0;
    for(int i=1; i<=n; i++)
    {
    outd[i] -= ind[i];
    if( outd[i] % 2 == 1 )
    {
    flag = 0;
    break;
    }
    outd[i] /= 2;
    if( outd[i] > 0 )
    {
    Add(0,i,outd[i]);
    sum += outd[i];
    }
    else
    Add(i,n+1,-outd[i]);
    }
    if( !flag )
    {
    printf("impossible\n");
    continue;
    }
    int ans = 0;
    while( BFS(0,n+1) )
    ans += Dinic(0,INT_MAX,0,n+1);
    if( ans == sum )
    printf("possible\n");
    else
    printf("impossible\n");
    }
    return 0;
    }



  • 相关阅读:
    缓存雪崩与缓存穿透
    读取表中最大值
    使用vscode在谷歌上运行代码
    elment 中tree组件展开所有和收缩所有节点
    深度系统商店提示无法安装软件依赖错误
    诗词,理解,品论
    《45个十分钟读懂资本论》原文、适合朗读版和个人见解
    《论持久战》全文
    OSError: [WinError 126] 找不到指定的模块。
    C++ 获取序列最大(或最小)的 N 个元素
  • 原文地址:https://www.cnblogs.com/huhuuu/p/2412433.html
Copyright © 2011-2022 走看看