• POJ1637Sightseeing tour/HDU3472HS BDC最大流Dinic+判断混合图的欧拉图


    前置知识:

    混合图:一幅图中既有单向边,又有双向边。

    混合图(既有有向边又有无向边的图)中欧拉环、欧拉路径的判定需要用到网络流这个算法!!!

    有向图的欧拉回路的条件:所有的节点出度等于入度。

    下面这两题基本差不多,但是建边啊、判断欧拉图啊等还是有区别的。

    总之最后都是需要判断是否为满流,如果为满流则说明是欧拉回路。

    注意:

    1、tot初始化为-1,因为在进行反向边的时候通过异或是01、23、45、...这样为一组的。

    if(di>0)
    {
        e[i].flow-=di;
        e[i^1].flow+=di;
        return di;
    }

    2、源点和汇点s和t要搞清楚设置为多少,有些题目设置s=n、t=n+1的时候会造成s->t没有边,从而造成错误。

    POJ1637-Sightseeing tour

    题意:问给出的混合图中是否存在欧拉回路。

    每行数据后面的0代表无向,1代表有向。

    AC代码:

      1 #include<string.h>
      2 #include<iostream>
      3 #include<stdio.h>
      4 #include<algorithm>
      5 #include<queue>
      6 #include<vector>
      7 #include<map>
      8 #include<cmath>
      9 using namespace std;
     10 #define inf 0x3f3f3f3f
     11 const int N=220;
     12 typedef long long ll;
     13 
     14 int n,m,s,t,tot;
     15 int head[10*N],dep[10*N],cur[10*N],floww;
     16 int in[N],out[N];
     17 
     18 struct node
     19 {
     20     // int u,v,flow;
     21     int nextt,v,flow;
     22 }e[N*N];
     23 
     24 void add(int u,int v,int flow)
     25 {
     26     tot++;
     27     //nextt[tot]=head[u];
     28     e[tot].nextt=head[u];
     29     head[u]=tot;
     30     // e[tot].u=u;
     31     e[tot].v=v;
     32     e[tot].flow=flow;
     33 
     34     /*  tot++;
     35       // nextt[tot]=head[v];
     36       e[tot].nextt=head[v];
     37       head[v]=tot;
     38       //e[tot].u=v;
     39       e[tot].v=u;
     40       e[tot].flow=0;*/
     41 }
     42 
     43 int dfs(int u,int flow)
     44 {
     45     if(u==t)
     46         return flow;
     47     for(int &i=cur[u]; i!=-1; i=e[i].nextt) //注意这里的&符号,这样i增加的同时也能改变cur[u]的值,达到记录当前弧的目的
     48     {
     49         if((dep[e[i].v]==dep[u]+1)&&e[i].flow>0)
     50         {
     51             int di=dfs(e[i].v,min(flow,e[i].flow));
     52             if(di>0)
     53             {
     54                 e[i].flow-=di;
     55                 e[i^1].flow+=di;
     56                 return di;
     57             }
     58         }
     59     }
     60     return -1;
     61 }
     62 
     63 bool bfs()
     64 {
     65     if(s==t)return 0;
     66     queue<int>Q;
     67     while(!Q.empty())
     68         Q.pop();
     69     memset(dep,-1,sizeof(dep));
     70     dep[s]=1;
     71     Q.push(s);
     72     while(!Q.empty())
     73     {
     74         int u=Q.front();
     75         Q.pop();
     76         for (int i=head[u]; i!=-1; i=e[i].nextt)
     77         {
     78             if ((e[i].flow>0)&&(dep[e[i].v]==-1))
     79             {
     80                 dep[e[i].v]=dep[u]+1;
     81                 Q.push(e[i].v);
     82             }
     83         }
     84     }
     85     if(dep[t]!=-1)
     86         return 1;
     87     return 0;
     88 }
     89 
     90 int dinic()
     91 {
     92     int sum=0;
     93     while(bfs())
     94     {
     95         for(int i=s; i<=t; i++)
     96             cur[i]=head[i];
     97         int di;
     98         while((di=dfs(s,inf))!=-1)
     99             sum+=di;
    100     }
    101     return sum;
    102 }
    103 
    104 bool Euler()
    105 {
    106     floww=0;
    107     for (int i=1; i<=n; i++)
    108     {
    109         if(in[i]<out[i])
    110             floww=floww+((out[i]-in[i])>>1);
    111         if((in[i]+out[i])&1)
    112             return 0;
    113     }
    114     return 1;
    115 }
    116 
    117 int main()
    118 {
    119     int tt;
    120     scanf("%d",&tt);
    121     while(tt--)
    122     {
    123         scanf("%d %d",&n,&m);
    124         memset(in,0,sizeof(in));
    125         memset(out,0,sizeof(out));
    126         memset(head,-1,sizeof(head));
    127         memset(cur,0,sizeof(cur));
    128         s=0,t=n+1,tot=-1;
    129         int x,y,z;
    130         for(int i=1; i<=m; i++)
    131         {
    132             scanf("%d %d %d",&x,&y,&z);
    133             in[y]++,out[x]++;
    134             if(z==0)
    135             {
    136                 add(x,y,1);
    137                 add(y,x,0);
    138             }
    139         }
    140         if(Euler())
    141         {
    142             for(int i=1; i<=n; i++)
    143             {
    144                 if(in[i]>out[i])
    145                 {
    146                     add(i,t,(in[i]-out[i])>>1);
    147                     add(t,i,0);
    148                 }
    149                 else if(out[i]>in[i])
    150                 {
    151                     add(s,i,(out[i]-in[i])>>1);
    152                     add(i,s,0);
    153                 }
    154             }
    155             if(dinic()==floww)
    156                 printf("possible\n");
    157             else
    158                 printf("impossible\n");
    159         }
    160         else
    161             printf("impossible\n");
    162     }
    163     return 0;
    164 }
    View Code

    这题我的代码再VJ上C++会超时,G++可以过。

    以后最好还是用G++交,因为G+兼容C和C++,但有时候C++能过G++不能,都试一下吧如果觉得自己代码实在是没问题了。

    输出double时,用G++提交时,scanf用%lf,prinf用%f,否则报错。

    HDU-3472-HS BDC

    题意:

    给n个字符串,如果某个字符串的最后一个字母和另外一个字符串的第一个字母字母一样,那么这两个字母就可以连起来,有的字符串可以反转,问是否存在一种情况使得所有字符串都连成链。

    思路:

    要知道判断的是欧拉回路或者欧拉通路,二者取其一即可;

    字符串的第一个字母–>字符串的最后一个字母建一条有向边,再判断字符串后面的数字x,看是否能够建立一条反向边,如果可以建立,则说明这条边是一条无向边,从而构成了一幅混合图

    由于成链而不是成环,所以可以利用Dinic中的SPFA,因为SPFA无法处理环。???

    但是这一题首先要判断一下建的图的连通性,只有满足连通才能进行下一步的判断

    AC代码:

      1 #include<string.h>
      2 #include<iostream>
      3 #include<stdio.h>
      4 #include<algorithm>
      5 #include<queue>
      6 #include<vector>
      7 #include<map>
      8 #include<cmath>
      9 using namespace std;
     10 #define inf 0x3f3f3f3f
     11 const int N=220;
     12 typedef long long ll;
     13 
     14 int n,m,tot,s,t;
     15 int head[10*N],dep[10*N],cur[10*N],floww;
     16 int in[30],out[30],f[30];
     17 char str[30];
     18 
     19 struct node
     20 {
     21     // int u,v,flow;
     22     int nextt,v,flow;
     23 } e[N*N];
     24 
     25 void add(int u,int v,int flow)
     26 {
     27     tot++;
     28     //nextt[tot]=head[u];
     29     e[tot].nextt=head[u];
     30     head[u]=tot;
     31     // e[tot].u=u;
     32     e[tot].v=v;
     33     e[tot].flow=flow;
     34 
     35       tot++;
     36       // nextt[tot]=head[v];
     37       e[tot].nextt=head[v];
     38       head[v]=tot;
     39       //e[tot].u=v;
     40       e[tot].v=u;
     41       e[tot].flow=0;
     42 }
     43 
     44 int dfs(int u,int flow)
     45 {
     46     if(u==t)
     47         return flow;
     48     for(int &i=cur[u]; i!=-1; i=e[i].nextt) //注意这里的&符号,这样i增加的同时也能改变cur[u]的值,达到记录当前弧的目的
     49     {
     50         if((dep[e[i].v]==dep[u]+1)&&e[i].flow>0)
     51         {
     52             int di=dfs(e[i].v,min(flow,e[i].flow));
     53             if(di>0)
     54             {
     55                 e[i].flow-=di;
     56                 e[i^1].flow+=di;
     57                 return di;
     58             }
     59         }
     60     }
     61     return -1;
     62 }
     63 
     64 bool bfs()
     65 {
     66     if(s==t)
     67         return 0;
     68     queue<int>Q;
     69     while(!Q.empty())
     70         Q.pop();
     71     memset(dep,-1,sizeof(dep));
     72     dep[s]=1;
     73     Q.push(s);
     74     while(!Q.empty())
     75     {
     76         int u=Q.front();
     77         Q.pop();
     78         for (int i=head[u]; i!=-1; i=e[i].nextt)
     79         {
     80             if ((e[i].flow>0)&&(dep[e[i].v]==-1))
     81             {
     82                 dep[e[i].v]=dep[u]+1;
     83                 Q.push(e[i].v);
     84             }
     85         }
     86     }
     87     if(dep[t]!=-1)
     88         return 1;
     89     return 0;
     90 }
     91 
     92 int dinic()
     93 {
     94     int sum=0;
     95     while(bfs())
     96     {
     97         for(int i=s; i<=t; i++)
     98             cur[i]=head[i];
     99         int di;
    100         while((di=dfs(s,inf))!=-1)
    101             sum+=di;
    102     }
    103     return sum;
    104 }
    105 
    106 //bool Euler()
    107 //{
    108 //    floww=0;
    109 //    for (int i=1; i<=26; i++)
    110 //    {
    111 //        if(in[i]<out[i])
    112 //            floww=floww+((out[i]-in[i])>>1);
    113 //        if((in[i]+out[i])&1)
    114 //            return 0;
    115 //    }
    116 //    return 1;
    117 //}
    118 
    119 int getf(int x)
    120 {
    121     if(f[x]==x)
    122         return x;
    123     return f[x]=getf(f[x]);
    124 }
    125 
    126 void merge(int x,int y)
    127 {
    128     int t1=getf(x);
    129     int t2=getf(y);
    130     f[t2]=t1;
    131 }
    132 
    133 bool judge_unpass()
    134 {
    135     int x=0;
    136     for(int i=1; i<=26; i++)
    137     {
    138         if(abs(in[i]-out[i])&1)
    139             x++;
    140     }
    141     if(x!=0&&x!=2)
    142         return 1;
    143     x=0;
    144     for(int i=1; i<=26; i++)
    145     {
    146         if((in[i]+out[i])&&f[i]==i)
    147             x++;
    148     }
    149     if(x>=2)
    150         return 1;
    151     return 0;
    152 }
    153 
    154 int main()
    155 {
    156     int cas=1,T;
    157     scanf("%d",&T);
    158     while(T--)
    159     {
    160         memset(in,0,sizeof(in));
    161         memset(out,0,sizeof(out));
    162         memset(head,-1,sizeof(head));
    163         memset(cur,0,sizeof(cur));
    164         s=0,t=27,tot=-1;
    165         for(int i=1; i<=26; i++)
    166             f[i]=i;
    167         scanf("%d",&m);
    168         for(int i=1; i<=m; i++)
    169         {
    170             int x;
    171             scanf("%s %d",str,&x);
    172             int len=strlen(str);
    173             int ss=str[0]-'a'+1;
    174             int tt=str[len-1]-'a'+1;
    175             in[tt]++,out[ss]++;
    176             merge(ss,tt);
    177             if(x)
    178             {
    179                 add(ss,tt,1);
    180                 //add(tt,ss,0);WA??
    181             }
    182         }
    183         if(judge_unpass())
    184             printf("Case %d: Poor boy!\n",cas++);
    185         else
    186         {
    187             int sum=0;
    188             for(int i=1; i<=26; i++)
    189             {
    190                 if(in[i]==0&&out[i]==0)
    191                     continue;
    192                 if(out[i]>in[i])
    193                 {
    194                     add(s,i,abs(in[i]-out[i])>>1);
    195                     sum+=abs(in[i]-out[i])>>1;
    196                 }
    197                 else if(out[i]<in[i])
    198                     add(i,t,abs(in[i]-out[i])>>1);
    199             }
    200             if(dinic()==sum)
    201                 printf("Case %d: Well done!\n",cas++);
    202             else
    203                 printf("Case %d: Poor boy!\n",cas++);
    204         }
    205     }
    206     return 0;
    207 }
    View Code
  • 相关阅读:
    19.1.25 [LeetCode8]String to Integer (atoi)
    19.1.23 CJK Round 1A 2015
    19.1.22 CJK Qualification Round 2015
    【转载】超级弹丸论破2再见绝望学园攻略
    19.1.20 [LeetCode 7]Reverse Integer
    19.1.20 [LeetCode 6]ZigZag Conversion
    19.1.20 [LeetCode 5]Longest Palindromic Substring
    python socket-select io多路复用
    web框架 源码
    python socket
  • 原文地址:https://www.cnblogs.com/OFSHK/p/12666577.html
Copyright © 2020-2023  润新知