POJ2531 Network Saboteur DFS 或 无向图的最大割

题目大意:给你一个无向完全图,让你求出该图的最大割。


分析:裸的最大割问题,随机算法就行,卡好时间。


实现代码如下:

#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;
}


你可能感兴趣的:(POJ2531 Network Saboteur DFS 或 无向图的最大割)