博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 6081 度度熊的王国战略(全局最小割堆优化)
阅读量:5145 次
发布时间:2019-06-13

本文共 4215 字,大约阅读时间需要 14 分钟。

Problem Description

度度熊国王率领着喵哈哈族的勇士,准备进攻哗啦啦族。
哗啦啦族是一个强悍的民族,里面有充满智慧的谋士,拥有无穷力量的战士。
所以这一场战争,将会十分艰难。
为了更好的进攻哗啦啦族,度度熊决定首先应该从内部瓦解哗啦啦族。
第一步就是应该使得哗啦啦族内部不能同心齐力,需要内部有间隙。
哗啦啦族一共有n个将领,他们一共有m个强关系,摧毁每一个强关系都需要一定的代价。
现在度度熊命令你需要摧毁一些强关系,使得内部的将领,不能通过这些强关系,连成一个完整的连通块,以保证战争的顺利进行。
请问最少应该付出多少的代价。
Input
本题包含若干组测试数据。
第一行两个整数n,m,表示有n个将领,m个关系。
接下来m行,每行三个整数u,v,w。表示u将领和v将领之间存在一个强关系,摧毁这个强关系需要代价w
数据范围:
2<=n<=3000
1<=m<=100000
1<=u,v<=n
1<=w<=1000
Output
对于每组测试数据,输出最小需要的代价。
Sample Input
2 1
1 2 1
3 3
1 2 5
1 2 4
2 3 3
Sample Output
1
3

题意

如上

题解

做法1.求全局最小割,由于点多边少,得用SW+堆优化(nmlogm)

做法2.S=1,随机T,求最小割,考虑到两个集合a和b,1肯定在a或b集合,也就是说随机的点只要在另外一个集合上,就有可能跑出最小割,特别要注意的是如果2999+1或者2998+2,会被卡到,所以可以特判掉这两种情况,另外>=3个点的概率还是挺高的(雾)

代码

SW+堆优化8080ms

1 #include
2 using namespace std; 3 4 const int maxn=3010; 5 const int maxm=2e5+5; 6 const int INF=0x3f3f3f3f; 7 8 int FIR[maxn],TO[maxm],NEXT[maxm],W[maxm],tote; 9 bool vis[maxn];10 int F[maxn],link[maxn],wage[maxn];11 int n,m;12 13 void add(int u,int v,int w)14 {15 TO[tote]=v;16 W[tote]=w;17 NEXT[tote]=FIR[u];18 FIR[u]=tote++;19 20 TO[tote]=u;21 W[tote]=w;22 NEXT[tote]=FIR[v];23 FIR[v]=tote++;24 }25 int Find(int x)26 {27 return x==F[x]?x:F[x]=Find(F[x]);28 }29 void Join(int u,int v)30 {31 int p=u;32 while(link[p]!=-1)p=link[p];33 link[p]=v;34 F[v]=u;35 }36 int MinCut(int cnt,int &s,int &t)37 {38 memset(wage,0,sizeof wage);39 memset(vis,false,sizeof vis);40 priority_queue< pair
>q;41 t=1;42 while(--cnt)43 {44 vis[s=t]=true;45 for(int u=s;u!=-1;u=link[u])46 {47 for(int p=FIR[u];p!=-1;p=NEXT[p])48 {49 int v=Find(TO[p]);50 if(!vis[v])51 q.push(make_pair(wage[v]+=W[p],v));52 }53 }54 t=0;55 while(!t)56 {57 if(q.empty())return 0;58 pair
pa=q.top();q.pop();59 if(wage[pa.second]==pa.first)60 t=pa.second;61 }62 }63 return wage[t];64 }65 int Stoer_Wagner()66 {67 int res=INF;68 for(int i=n,s,t;i>1;i--)69 {70 res=min(res,MinCut(i,s,t));71 if(res==0)break;72 Join(s,t);73 }74 return res;75 }76 void init()77 {78 tote=0;79 for(int i=1;i<=n;i++)FIR[i]=link[i]=-1,F[i]=i;80 }81 int main()82 {83 while(scanf("%d%d",&n,&m)!=EOF)84 {85 init();86 for(int i=0,u,v,w;i

随机算法2402ms

1 #include
2 using namespace std; 3 4 const int maxn=3005; 5 const int maxm=2e5+5;//至少总M*2 6 const int INF=0x3f3f3f3f; 7 8 int TO[maxm],CAP[maxm],NEXT[maxm],tote; 9 int FIR[maxn],gap[maxn],cur[maxn],d[maxn],q[400000],u[maxm],v[maxm],w[maxm];10 int n,m,S,T;11 12 void add(int u,int v,int cap)13 {14 //printf("i=%d %d %d %d\n",tote,u,v,cap);15 TO[tote]=v;16 CAP[tote]=cap;17 NEXT[tote]=FIR[u];18 FIR[u]=tote++;19 20 TO[tote]=u;21 CAP[tote]=0;22 NEXT[tote]=FIR[v];23 FIR[v]=tote++;24 }25 void bfs()26 {27 memset(gap,0,sizeof gap);28 memset(d,0,sizeof d);29 ++gap[d[T]=1];30 for(int i=1;i<=n;++i)cur[i]=FIR[i];31 int head=1,tail=1;32 q[1]=T;33 while(head<=tail)34 {35 int u=q[head++];36 for(int v=FIR[u];v!=-1;v=NEXT[v])37 if(!d[TO[v]])38 ++gap[d[TO[v]]=d[u]+1],q[++tail]=TO[v];39 }40 }41 int dfs(int u,int fl)42 {43 if(u==T)return fl;44 int flow=0;45 for(int &v=cur[u];v!=-1;v=NEXT[v])46 if(CAP[v]&&d[u]==d[TO[v]]+1)47 {48 int Min=dfs(TO[v],min(fl,CAP[v]));49 flow+=Min,fl-=Min,CAP[v]-=Min,CAP[v^1]+=Min;50 if(!fl)return flow;51 }52 if(!(--gap[d[u]]))d[S]=n+1;53 ++gap[++d[u]],cur[u]=FIR[u];54 return flow;55 }56 int ISAP()57 {58 bfs();59 int ret=0;60 while(d[S]<=n)ret+=dfs(S,INF);61 return ret;62 }63 void init()64 {65 tote=0;66 memset(FIR,-1,sizeof FIR);67 }68 int main()69 {70 srand(time(NULL));71 while(scanf("%d%d",&n,&m)!=EOF)72 {73 int wage[maxn]={
0};74 for(int i=0;i

 

转载于:https://www.cnblogs.com/taozi1115402474/p/9607436.html

你可能感兴趣的文章
WebForm——IIS服务器、开发方式和简单基础
查看>>
小实验3:实现haproxy的增、删、查
查看>>
Angular中ngModel的$render的详解
查看>>
读《格局》| 未到年纪的真理
查看>>
[转]《城南旧事》里的《送别》
查看>>
07动手动脑
查看>>
django知识点总结
查看>>
C++ STL stack、queue和vector的使用
查看>>
OAuth2 .net MVC实现获取token
查看>>
java中XML操作:xml与string互转、读取XML文档节点及对XML节点增删改查
查看>>
Nginx多域名配置
查看>>
使用Reporting Services时遇到的小问题
查看>>
传递事件和传递命令系统···
查看>>
约瑟夫问题
查看>>
Arduino 报错总结
查看>>
树莓派Android Things物联网开发:树莓派GPIO引脚图
查看>>
Database、User、Schema、Tables、Col、Row
查看>>
ckplayer网页播放器简易教程
查看>>
Android Studio 学习(六)内容提供器
查看>>
作业1:求500到1000之间有多少个素数,并打印出来
查看>>