HDU3987 Harry Potter and the Forbidden Forest(边数最少的最小割)

方法1:两遍最大流。一遍最大流后,把满流边容量+1,非满流边改为INF;再求最小割即为答案。

我大概想了下证明:能构成最小割的边在第一次跑最大流时都满流,然后按那样改变边容量再求一次最小割,就相当于再在那些 满流可能是属于最小割的边 中挑出最少的边形成ST割。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 #include<algorithm>
  5 using namespace std;
  6 #define INF (1LL<<60)
  7 #define MAXN 1111
  8 #define MAXM 440000
  9
 10 struct Edge{
 11     int v,next;
 12     __int64 cap,flow;
 13 }edge[MAXM];
 14 int vs,vt,NE,NV;
 15 int head[MAXN];
 16
 17 void addEdge(int u,int v,__int64 cap){
 18     edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=0;
 19     edge[NE].next=head[u]; head[u]=NE++;
 20     edge[NE].v=u; edge[NE].cap=0; edge[NE].flow=0;
 21     edge[NE].next=head[v]; head[v]=NE++;
 22 }
 23
 24 int level[MAXN];
 25 int gap[MAXN];
 26 void bfs(){
 27     memset(level,-1,sizeof(level));
 28     memset(gap,0,sizeof(gap));
 29     level[vt]=0;
 30     gap[level[vt]]++;
 31     queue<int> que;
 32     que.push(vt);
 33     while(!que.empty()){
 34         int u=que.front(); que.pop();
 35         for(int i=head[u]; i!=-1; i=edge[i].next){
 36             int v=edge[i].v;
 37             if(level[v]!=-1) continue;
 38             level[v]=level[u]+1;
 39             gap[level[v]]++;
 40             que.push(v);
 41         }
 42     }
 43 }
 44
 45 int pre[MAXN];
 46 int cur[MAXN];
 47 __int64 ISAP(){
 48     bfs();
 49     memset(pre,-1,sizeof(pre));
 50     memcpy(cur,head,sizeof(head));
 51     int u=pre[vs]=vs;
 52     __int64 flow=0,aug=INF;
 53     gap[0]=NV;
 54     while(level[vs]<NV){
 55         bool flag=false;
 56         for(int &i=cur[u]; i!=-1; i=edge[i].next){
 57             int v=edge[i].v;
 58             if(edge[i].cap!=edge[i].flow && level[u]==level[v]+1){
 59                 flag=true;
 60                 pre[v]=u;
 61                 u=v;
 62                 //aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
 63                 aug=min(aug,edge[i].cap-edge[i].flow);
 64                 if(v==vt){
 65                     flow+=aug;
 66                     for(u=pre[v]; v!=vs; v=u,u=pre[u]){
 67                         edge[cur[u]].flow+=aug;
 68                         edge[cur[u]^1].flow-=aug;
 69                     }
 70                     //aug=-1;
 71                     aug=INF;
 72                 }
 73                 break;
 74             }
 75         }
 76         if(flag) continue;
 77         int minlevel=NV;
 78         for(int i=head[u]; i!=-1; i=edge[i].next){
 79             int v=edge[i].v;
 80             if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
 81                 minlevel=level[v];
 82                 cur[u]=i;
 83             }
 84         }
 85         if(--gap[level[u]]==0) break;
 86         level[u]=minlevel+1;
 87         gap[level[u]]++;
 88         u=pre[u];
 89     }
 90     return flow;
 91 }
 92 int main(){
 93     int t,n,m,a,b,c,d;
 94     scanf("%d",&t);
 95     for(int cse=1; cse<=t; ++cse){
 96         scanf("%d%d",&n,&m);
 97         vs=0; vt=n-1; NV=n; NE=0;
 98         memset(head,-1,sizeof(head));
 99         while(m--){
100             scanf("%d%d%d%d",&a,&b,&c,&d);
101             if(d){
102                 addEdge(a,b,c);
103                 addEdge(b,a,c);
104             }else{
105                 addEdge(a,b,c);
106             }
107         }
108         ISAP();
109         for(int i=0; i<NE; i+=2){
110             if(edge[i].flow==edge[i].cap) ++edge[i].cap;
111             else edge[i].cap=INF;
112         }
113         printf("Case %d: %I64d\n",cse,ISAP());
114     }
115     return 0;
116 }

方法2:放大边权。把每条边的容量cap改为cap*m+1,m为一个够大的数(总边数+1就够了)。最后跑一遍最大流,最小割为maxflow/m,最少边数为maxflow%m。

我大概想了下证明:原图流量能满的,新图流量肯定也能达到cap*m,因为可以把新图看成是m张原图。而流量达到cap*m的边还剩1这个容量还没用到(流量达不到cap*m自然就用不到这个1容量了),那么就相当于在这些边的基础上再跑一遍最大流,与方法1差不多的道理。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 #include<algorithm>
  5 using namespace std;
  6 #define INF (1LL<<60)
  7 #define MAXN 1111
  8 #define MAXM 440000
  9
 10 struct Edge{
 11     int v,next;
 12     __int64 cap,flow;
 13 }edge[MAXM];
 14 int vs,vt,NE,NV;
 15 int head[MAXN];
 16
 17 void addEdge(int u,int v,__int64 cap){
 18     edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=0;
 19     edge[NE].next=head[u]; head[u]=NE++;
 20     edge[NE].v=u; edge[NE].cap=0; edge[NE].flow=0;
 21     edge[NE].next=head[v]; head[v]=NE++;
 22 }
 23
 24 int level[MAXN];
 25 int gap[MAXN];
 26 void bfs(){
 27     memset(level,-1,sizeof(level));
 28     memset(gap,0,sizeof(gap));
 29     level[vt]=0;
 30     gap[level[vt]]++;
 31     queue<int> que;
 32     que.push(vt);
 33     while(!que.empty()){
 34         int u=que.front(); que.pop();
 35         for(int i=head[u]; i!=-1; i=edge[i].next){
 36             int v=edge[i].v;
 37             if(level[v]!=-1) continue;
 38             level[v]=level[u]+1;
 39             gap[level[v]]++;
 40             que.push(v);
 41         }
 42     }
 43 }
 44
 45 int pre[MAXN];
 46 int cur[MAXN];
 47 __int64 ISAP(){
 48     bfs();
 49     memset(pre,-1,sizeof(pre));
 50     memcpy(cur,head,sizeof(head));
 51     int u=pre[vs]=vs;
 52     __int64 flow=0,aug=INF;
 53     gap[0]=NV;
 54     while(level[vs]<NV){
 55         bool flag=false;
 56         for(int &i=cur[u]; i!=-1; i=edge[i].next){
 57             int v=edge[i].v;
 58             if(edge[i].cap!=edge[i].flow && level[u]==level[v]+1){
 59                 flag=true;
 60                 pre[v]=u;
 61                 u=v;
 62                 //aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
 63                 aug=min(aug,edge[i].cap-edge[i].flow);
 64                 if(v==vt){
 65                     flow+=aug;
 66                     for(u=pre[v]; v!=vs; v=u,u=pre[u]){
 67                         edge[cur[u]].flow+=aug;
 68                         edge[cur[u]^1].flow-=aug;
 69                     }
 70                     //aug=-1;
 71                     aug=INF;
 72                 }
 73                 break;
 74             }
 75         }
 76         if(flag) continue;
 77         int minlevel=NV;
 78         for(int i=head[u]; i!=-1; i=edge[i].next){
 79             int v=edge[i].v;
 80             if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
 81                 minlevel=level[v];
 82                 cur[u]=i;
 83             }
 84         }
 85         if(--gap[level[u]]==0) break;
 86         level[u]=minlevel+1;
 87         gap[level[u]]++;
 88         u=pre[u];
 89     }
 90     return flow;
 91 }
 92 int main(){
 93     int t,n,m,a,b,c,d;
 94     scanf("%d",&t);
 95     for(int cse=1; cse<=t; ++cse){
 96         scanf("%d%d",&n,&m);
 97         vs=0; vt=n-1; NV=n; NE=0;
 98         memset(head,-1,sizeof(head));
 99         __int64 x=m<<1|1;
100         while(m--){
101             scanf("%d%d%d%d",&a,&b,&c,&d);
102             if(d){
103                 addEdge(a,b,c*x+1);
104                 addEdge(b,a,c*x+1);
105             }else{
106                 addEdge(a,b,c*x+1);
107             }
108         }
109         printf("Case %d: %I64d\n",cse,ISAP()%x);
110     }
111     return 0;
112 }

时间: 2024-10-17 13:16:32

HDU3987 Harry Potter and the Forbidden Forest(边数最少的最小割)的相关文章

hdu 3987 Harry Potter and the Forbidden Forest 求割边最少的最小割

view code//hdu 3987 #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> using namespace std; typedef long long ll; const ll INF = 1LL<<59; const ll E = 100001; const int N = 10

hdu 3987 Harry Potter and the Forbidden Forest【网路流最小割模型】

Harry Potter and the Forbidden Forest Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1549    Accepted Submission(s): 528 Problem Description Harry Potter notices some Death Eaters try to slip

HDU 3987 Harry Potter and the Forbidden Forest(最小割中的最少割边)经典

Harry Potter and the Forbidden Forest Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1791    Accepted Submission(s): 596 Problem Description Harry Potter notices some Death Eaters try to slip

Harry Potter and the Forbidden Forest(割边最小的最小割)

Harry Potter and the Forbidden Forest Time Limit:3000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u Description Harry Potter notices some Death Eaters try to slip into Castle. The Death Eaters hide in the most depths of Forbidden Forest.

hdoj 3987 Harry Potter and the Forbidden Forest 【求所有最小割里面 最少的边数】

Harry Potter and the Forbidden Forest Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1802    Accepted Submission(s): 602 Problem Description Harry Potter notices some Death Eaters try to slip

题单二:图论500

http://wenku.baidu.com/link?url=gETLFsWcgddEDRZ334EJOS7qCTab94qw5cor8Es0LINVaGMSgc9nIV-utRIDh--2UwRLvsvJ5tXFjbdpzbjygEdpGehim1i5BfzYgYWxJmu ==========  以下是最小生成树+并查集=========================[HDU]1213         How Many Tables        基础并查集★1272         小

图论五百题!

生死看淡不服就淦,这才是人生! =============================以下是最小生成树+并查集======================================[HDU]1213 How Many Tables 基础并查集★1272 小希的迷宫 基础并查集★1325&&poj1308 Is It A Tree? 基础并查集★1856 More is better 基础并查集★1102 Constructing Roads 基础最小生成树★1232 畅通工程 基

图论 500题——主要为hdu/poj/zoj

转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并查集======================================[HDU]1213   How Many Tables   基础并查集★1272   小希的迷宫   基础并查集★1325&&poj1308  Is It A Tree?   基础并查集★1856   More i

图论精炼500题

忘了从哪转的了... =============================以下是最小生成树+并查集====================================== [HDU] 1213               How Many Tables                    基础并查集★ 1272               小希的迷宫                     基础并查集★ 1325&&poj1308    Is It A Tree?