Special Fish
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2215 Accepted Submission(s): 833
Problem Description
There is a kind of special fish in the East Lake where is closed to campus of Wuhan University. It’s hard to say which gender of those fish are, because every fish believes itself as a male, and it may attack one of some other fish who is believed to be female by it.
A fish will spawn after it has been attacked. Each fish can attack one other fish and can only be attacked once. No matter a fish is attacked or not, it can still try to attack another fish which is believed to be female by it.
There is a value we assigned to each fish and the spawns that two fish spawned also have a value which can be calculated by XOR operator through the value of its parents.
We want to know the maximum possibility of the sum of the spawns.
Input
The input consists of multiply test cases. The first line of each test case contains an integer n (0 < n <= 100), which is the number of the fish. The next line consists of n integers, indicating the value (0 < value <= 100) of each fish. The next n lines, each line contains n integers, represent a 01 matrix. The i-th fish believes the j-th fish is female if and only if the value in row i and column j if 1.
The last test case is followed by a zero, which means the end of the input.
Output
Output the value for each test in a single line.
Sample Input
3
1 2 3
011
101
110
0
Sample Output
6
Author
momodi@whu
Source
The 5th Guangting Cup Central China Invitational Programming Contest
题目大意:
有n条鱼,每条鱼都有一个权值,然后给出一个n*n的一个邻接矩阵,如果map【i】【j】==1表示i可以攻击J,其能够获得的价值是val【i】^ val【j】;每一条鱼只能攻击一次,也只能被攻击一次,问最大获得价值。
思路:
1、首先,对于建图:
①建立超级源点,将源点连入每一条鱼(1-n),其权值设定为1,费用设定为0,表示每一条鱼只能攻击出去一次。
②建立超级汇点,将每条鱼的拆点(n+1-2n)连入汇点,其权值设定为1,费用设定为0,表示每一条鱼只能被攻击一次。
③将每一条鱼(1-n)连入其拆点(n+1-2n)【当然要求是能够攻击的鱼】,其权值设定为1,费用设定为val【i】^val【j】。表示某条鱼攻击出去之后,会获得的价值。
2、然后注意这个题不需要最大流时候的最大费用,而是求一个最大费用,无论在什么流时候都行,那么我们跑最长路过后,如果发现这条最长路是负权值的时候,那么就要直接退出。(因为退回边的作用,会在跑最长路的时候出现负权值)。
Ac代码:
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
#define INF 0x3f3f3f3f
struct node
{
int from;
int to;
int next;
int w;
int f;
int num;
}e[100*100*5];
int vis[2050];
int pre[2050];
int path[2050];
int dis[2050];
int head[2050];
char a[150][150];
int val[2050];
int n,cont,ss,tt;
void add(int from,int to,int w,int f)
{
e[cont].to=to;
e[cont].f=f;
e[cont].w=w;
e[cont].num=cont;
e[cont].next=head[from];
head[from]=cont++;
}
void getmap()
{
ss=2*n+1;
tt=ss+1;
cont=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
{
add(ss,i,0,1);
add(i,ss,0,0);
add(i+n,tt,0,1);
add(tt,i+n,0,0);
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(a[i][j]=='1')
{
int u=i+1;
int v=j+1+n;
add(u,v,val[i+1]^val[j+1],1);
add(v,u,-(val[i+1]^val[j+1]),0);
}
}
}
}
int SPFA()
{
queue<int >s;
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));
memset(path,-1,sizeof(path));
for(int i=0;i<=tt;i++)dis[i]=-0x3f3f3f3f;
vis[ss]=1;
dis[ss]=0;
s.push(ss);
while(!s.empty())
{
int u=s.front();
s.pop();vis[u]=0;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
int f=e[i].f;
if(f>0&&dis[v]<dis[u]+w)
{
dis[v]=dis[u]+w;
pre[v]=u;
path[v]=e[i].num;
if(vis[v]==0)
{
vis[v]=1;
s.push(v);
}
}
}
}
if(dis[tt]!=0x3f3f3f3f)return 1;
else return 0;
}
void Maxcost_Maxflow()
{
int ans=0;
int maxflow=0;
while(SPFA()==1)
{
if(dis[tt]<0)break;
int minn=INF;
for(int i=tt;i!=ss;i=pre[i])
{
minn=min(minn,e[path[i]].f);
}
for(int i=tt;i!=ss;i=pre[i])
{
e[path[i]].f-=minn;
e[path[i]^1].f+=minn;
}
ans+=dis[tt];
maxflow+=minn*dis[tt];
}
printf("%d\n",ans);
}
int main()
{
while(~scanf("%d",&n))
{
if(n==0)break;
for(int i=1;i<=n;i++)
{
scanf("%d",&val[i]);
}
for(int i=0;i<n;i++)
{
scanf("%s",a[i]);
}
getmap();
Maxcost_Maxflow();
}
return 0;
}

本文介绍了一个关于特殊鱼类的问题,通过构建一个复杂的图模型,并运用最大费用流算法来解决该问题,旨在找到所有可能配对中价值最大的组合。
482

被折叠的 条评论
为什么被折叠?



