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

来源:互联网 发布:淘宝闲鱼钓鱼网站源码 编辑:程序博客网 时间:2024/05/21 18:41

题意:

    求最小割,但因为最小割是不唯一的,题目要求得到最小割的条件下,使得割边最少,输出最少割边数

思路:

    有两种做法,但本质是一样的

  第一种:
    建边的时候每条边权 w = w * (E + 1) + 1;
    这样得到最大流 maxflow / (E + 1) ,最少割边数 maxflow % (E + 1)

    道理很简单,如果原先两类割边都是最小割,那么求出的最大流相等
    但边权变换后只有边数小的才是最小割了

    乘(E+1)是为了保证边数叠加后依然是余数,不至于影响求最小割的结果

  第二种:

    建图,得到最大流后,图中边若满流,说明该边是最小割上的边

    再建图,原则:满流的边改为容量为 1 的边,未满流的边改为容量 INF 的边,然后最大流即答案

 

由于题目需要乘上最大的边数  而题目的最大边数有100000 所以数会很大 需要用64.在错了无限多次后终于搞对了。记得是他的花费要超int

还有就是记得用c++编译不用g++不然inf会超long int

 先给出方法1的:耗时间78ms

#include<iostream> #include<cstdio> #include<memory.h> #include<cmath> using namespace std;   #define MAXN 5010 #define MAXE 1000100 #define INF 100000000000000000   int ne,nv,tmp,s,t,index;  struct Edge{     int next,pair,v;     __int64 cap,fLow; }edge[MAXE]; int net[MAXN]; __int64 ISAP() {     int numb[MAXN],dist[MAXN],curedge[MAXN],pre[MAXN];     __int64 cur_fLow,max_fLow;int u,tmp,neck,i;     memset(dist,0,sizeof(dist));     memset(numb,0,sizeof(numb));     memset(pre,-1,sizeof(pre));     for(i = 1 ; i <= nv ; ++i)         curedge[i] = net[i];     numb[nv] = nv;     max_fLow = 0;     u = s;     while(dist[s] < nv)     {         if(u == t)         {             cur_fLow = INF+1;             for(i = s; i != t;i = edge[curedge[i]].v)              {                   if(cur_fLow > edge[curedge[i]].cap)                 {                     neck = i;                     cur_fLow = edge[curedge[i]].cap;                 }             }             for(i = s; i != t; i = edge[curedge[i]].v)             {                 tmp = curedge[i];                 edge[tmp].cap -= cur_fLow;                 edge[tmp].fLow += cur_fLow;                 tmp = edge[tmp].pair;                 edge[tmp].cap += cur_fLow;                 edge[tmp].fLow -= cur_fLow;             }             max_fLow += cur_fLow;             u = neck;         }        for(i = curedge[u]; i != -1; i = edge[i].next)             if(edge[i].cap > 0 && dist[u] == dist[edge[i].v]+1)                 break;         if(i != -1)         {             curedge[u] = i;             pre[edge[i].v] = u;             u = edge[i].v;         }else{             if(0 == --numb[dist[u]]) break;             curedge[u] = net[u];             for(tmp = nv,i = net[u]; i != -1; i = edge[i].next)                 if(edge[i].cap > 0)                     tmp = tmp<dist[edge[i].v]?tmp:dist[edge[i].v];             dist[u] = tmp + 1;             ++numb[dist[u]];             if(u != s) u = pre[u];         }     }          return max_fLow; }void addedge(int u,int v,__int64 f){    edge[index].next = net[u];     edge[index].v = v;     edge[index].cap = f;     edge[index].fLow = 0;     edge[index].pair = index+1;     net[u] = index++;     edge[index].next = net[v];     edge[index].v = u;     edge[index].cap = 0;     edge[index].fLow = 0;     edge[index].pair = index-1;     net[v] = index++;    } int main() {     int i,j,np,nc,m,n;     int a,b,d,k,vaL;    int te;    int cases=1;    scanf("%d",&te);     while(te--)     {         scanf("%d%d",&n,&m);        nv=n;        index=1;        if(n==0 && m==0) return 0;        s = 1;         t = n;         memset(net,-1,sizeof(net));                        for(i=1;i<=m;i++)         {             int u,v,d;            __int64 c;            scanf("%d%d%I64d%d",&u,&v,&c,&d);            u++,v++;            addedge(u,v,c*100001+1);             if(d)            addedge(v,u,c*100001+1);         }                 __int64 ans=ISAP();        printf("Case %d: %I64d\n", cases++, ans % 100001);    }     return 0; }


 

 

原创粉丝点击