您的位置:首页 > 其它

zoj 3135 Party of 8g 最大点权独立集

2015-08-05 16:00 441 查看
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3165

题意:有M个男孩和N个女孩 他们每个人都有一个love值。

现在要邀请他们中的一部分人,满足他们之间没有“8g”关系。

给出M,N,S. S表示有S对boy和girl之间有“8g”关系。

思路:

最大点权独立集。

原图基础上增加源s和汇t。

s向每个boy连一条边,容量为这个人的love值。

每个girl向t连一条边,容量为这个人的love值。

然后每对"bg"关系boy向girl连一条边,容量为正无穷。

求最小割。答案 = 权值总和 - 最小割

再输出哪几个男孩和女孩被邀请了。

#include <bits/stdc++.h>
using namespace std;
#define maxn 205
const int inf = 0x3f3f3f3f;
struct Edge
{
int from, to, cap, flow;
Edge(int f, int t, int c, int fl)
{
from = f; to = t; cap = c; flow = fl;
}
};
vector <Edge> edges;
vector <int> G[maxn];
int vis[maxn], cur[maxn], d[maxn];
int s, t, n, m;
void AddEdge(int from, int to, int cap)
{
edges.push_back(Edge(from, to, cap, 0));
edges.push_back(Edge(to, from, 0, 0));
m = edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool bfs()
{
memset(vis, 0, sizeof(vis));
d[s] = 0;
vis[s] = 1;
queue <int> q;
q.push(s);
while(!q.empty())
{
int u = q.front(); q.pop();
for(int i = 0 ; i < G[u].size(); i++)
{
Edge &e = edges[G[u][i]];
if(!vis[e.to] && e.cap > e.flow)
{
d[e.to] = d[u]+1;
vis[e.to] = 1;
q.push(e.to);
}
}
}
return vis[t];
}
int dfs(int x, int a)
{
if(x == t || a == 0) return a;
int flow = 0, f;
for(int &i = cur[x]; i < G[x].size(); i++)
{
Edge &e = edges[G[x][i]];
if(d[x] + 1 == d[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0)
{
e.flow += f;
edges[G[x][i]^1].flow -= f;
flow += f;
a -= f;
if(a == 0) break;
}
}
return flow;
}
int Maxflow()
{
int flow = 0;
while(bfs())
{
memset(cur, 0, sizeof(cur));
flow += dfs(s, inf);
}
return flow;
}
int N, M, S;
int b[110], g[110];
int main()
{
while(~scanf("%d%d%d", &M, &N, &S))
{
edges.clear();
for(int i = 0; i <= N+M+1; i++) G[i].clear();
s = 0; t = N+M+1;
int temp;
int sum = 0;
memset(b, 0, sizeof(b));
memset(g, 0, sizeof(g));
for(int i = 1; i <= M; i++) //BOY
{
scanf("%d", &temp);
sum += temp;
AddEdge(s, i, temp);
}
for(int i = 1; i <= N; i++) //GIRL
{
scanf("%d", &temp);
sum += temp;
AddEdge(i+M, t, temp);
}
for(int i = 1; i <= S; i++)
{
int a, b; scanf("%d%d", &a, &b);
AddEdge(a, b+M, inf);
}
int flow = Maxflow();
sum -= flow;
//cout<<sum<<endl;
int cntb = 0, cntg = 0;
for(int i = 0; i < m; i+=2)
{
if(edges[i].from == s)
{
if(vis[edges[i].to])
{
b[edges[i].to] = 1;
cntb++;
}

}
if(edges[i].to == t)
{
if(!vis[edges[i].from])
{
g[edges[i].from-M] = 1;
cntg++;
}
}
}
printf("%d %d %d\n", sum, cntb, cntg);
bool flag = true;
for(int i = 1; i <= M; i++)
{
if(b[i])
{
if(flag) printf("%d", i), flag = false;
else printf(" %d",i);
}
}
printf("\n");
flag = true;
for(int i = 1; i <= N; i++)
{
if(g[i])
{
if(flag) printf("%d", i), flag = false;
else printf(" %d", i);
}
}
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: