题目大意:给你一个无向完全图,让你求出该图的最大割。
分析:裸的最大割问题,随机算法就行,卡好时间。
实现代码如下:
#include <cstdio> #include <cstdlib> #include <iostream> using namespace std; int maze[25][25]; int main() { int n; while(scanf("%d",&n)!=-1) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&maze[i][j]); bool vis[25]={0};//用0和1表示图中的顶点在哪个集合中 int time=2000*100;//随机次数要尽量大 long long ans=0;//纪录结果 long long cnt=0;//纪录当前最大值 while(time--) { int x=rand()%n+1;//生成随机数 vis[x]=!vis[x];//改变x所在的集合 for(int i=1;i<=n;i++)//枚举和x相连的每一个顶点 { if(vis[x]!=vis[i])//如果i和x不在同一个集合中,就把权值加到cnt上 cnt+=maze[x][i]; else if(x!=i)//i和x改变集合之前在一个集合中,那么减去由于x改变而多增加的这些权值 cnt-=maze[x][i]; } if(ans<cnt) ans=cnt; } printf("%lld\n",ans); } return 0; }
这道题也可以用深搜来做,从第一个点开始枚举,每个点都有两种状态(代表属于两个集合),然后分别回溯。
实现代码如下:
#include <cstdio> #include <iostream> using namespace std; int maze[25][25]; int n,ans; bool s[25]; void dfs(int cnt,int sum) { if(cnt>n) { if(ans<sum) ans=sum; return ; } int m; m=0; s[cnt]=1; for(int i=1;i<=cnt;i++) if(!s[i]) m+=maze[cnt][i]; dfs(cnt+1,sum+m); m=0; s[cnt]=0; for(int i=1;i<=cnt;i++) if(s[i]) m+=maze[cnt][i]; dfs(cnt+1,sum+m); } int main() { while(scanf("%d",&n)!=-1) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&maze[i][j]); ans=0; dfs(1,0); printf("%d\n",ans); } return 0; }