zoj 3165 Party of 8g (最大点权独立集)

来源:互联网 发布:数据库一般多大内存 编辑:程序博客网 时间:2024/06/06 08:26
Party of 8g

Time Limit: 5 Seconds      Memory Limit: 56797 KB      Special Judge

As all you know, DD is a hospitable person. On Saint Valentine's Day, DD is going to arrang a party for girls and boys. However, as you may don't know, DD hate the so-called "8g" relationship. So, he will not invite a boy and a girl who have 8g at the same time.

DD's friends are M boys (labeled 1..M) and N girls (labeled 1..N), and each of them has a "lovely value". Now, DD want to invite some of them, satisfying that no 8g exists among invited people, and the total lovely value of all the invited people can be maximal.

Input

Multiple test cases, each cases consists of three parts.

First part, one line, three integers MN and S.

Second part, two lines. First line, M integers, boys' lovely values from the 1st to the Mth. Second line, N integers, girls' lovely values from the 1st to the Nth.

Third part, S lines. Each line consists of two integers X and Y, means that the boy X and the girl Y have 8g.

One blank line between test cases.

Output

For each test case, your output should include three parts.

First part, one line, three integers XA and BX is the maximal total lovly value. A and B are the numbers of boys and girls invited.

Second part, one line, A integers, labels of the invited boys.

Third part, one line, B integers, labels of the invited girls.

If multiple solutions exist, output any of them.

Data Restriction

0 <= MN <= 100; 0 <= S <= M*N.

1 <= lovely value <= 1024.

Sample Input

5 5 101 3 5 7 92 4 6 8 101 45 32 43 51 12 41 23 41 55 5

Sample Output

37 1 541 2 3 4 5

Author: CUI, Tianyi
Source: ZOJ Monthly, February 2009


求二分图的最大点权独立集, 等于总权值 - 最小点权覆盖集。最小点权覆盖集就是最小割。最小割的方案是在求过最大流的残留网络中,从s出发遍历所有的点,构成集合S。再根据S判断。

#include<cstdio>#include<map>#include<queue>#include<cstring>#include<iostream>#include<algorithm>#include<vector>#include<list>#include<set>#include<cmath>using namespace std;const int maxn = 1e5 + 5;const int INF = 1e9;const double eps = 1e-6;typedef unsigned long long ULL;typedef long long LL;typedef pair<int, int> P;#define fi first#define se secondstruct Edge {  int from, to, cap, flow;};struct Dinic {  int n, m, s, t;  vector<Edge> edges;    // 边数的两倍  vector<int> G[maxn];   // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号  bool vis[maxn];        // BFS使用  int d[maxn];           // 从起点到i的距离  int cur[maxn];         // 当前弧指针  void ClearAll(int n) {    for(int i = 0; i < n; i++) G[i].clear();    edges.clear();  }  void ClearFlow() {    for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;  }  void AddEdge(int from, int to, int cap) {    //cout << from << ' ' << to << ' ' << cap << endl;    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));    queue<int> Q;    Q.push(s);    vis[s] = 1;    d[s] = 0;    while(!Q.empty()) {      int x = Q.front(); Q.pop();      for(int i = 0; i < G[x].size(); i++) {        Edge& e = edges[G[x][i]];        if(!vis[e.to] && e.cap > e.flow) {          vis[e.to] = 1;          d[e.to] = d[x] + 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 s, int t) {    this->s = s; this->t = t;    int flow = 0;    while(BFS()) {      memset(cur, 0, sizeof(cur));      flow += DFS(s, INF);    }    return flow;  }  vector<int> boy, girl;  void get_ans(int a, int b){    boy.clear();girl.clear();    int vis[maxn];    memset(vis, 0, sizeof vis);    queue<int> q;    q.push(0);    while(!q.empty()){        int pos = q.front();q.pop();        for(int i = 0;i < G[pos].size();i++){            Edge& e = edges[G[pos][i]];            if(e.cap > e.flow && !vis[e.to]){                vis[e.to] = 1;                q.push(e.to);            }        }    }    for(int i = 1;i <= a;i++){        if(vis[i]==1)            boy.push_back(i);    }    for(int i = a+1;i <= a+b;i++){        if(vis[i]==0)            girl.push_back(i-a);    }  }};Dinic g;int main(){    int a, b, m;    while(scanf("%d%d%d", &a, &b, &m) != EOF){        g.ClearAll(a+b+5);        int source = 0, sink = a+b+1;        int total = 0;        for(int i = 1;i <= a;i++){            int x;            scanf("%d", &x);            total += x;            g.AddEdge(source, i, x);        }        for(int i = 1;i <= b;i++){            int x;            scanf("%d", &x);            total += x;            g.AddEdge(i+a, sink, x);        }        while(m--){            int x, y;            scanf("%d%d", &x, &y);            g.AddEdge(x, a+y, INF);        }        cout << total-g.Maxflow(source, sink);        g.get_ans(a, b);        cout << ' ' << g.boy.size() << ' ' << g.girl.size() << endl;        int bsize = g.boy.size();        for(int i = 0;i < bsize-1;i++){            cout << g.boy[i] << ' ';        }        if(bsize>=1)            cout << g.boy[bsize-1];        cout << endl;        int gsize = g.girl.size();        for(int i = 0;i < gsize-1;i++){            cout << g.girl[i] << ' ';        }        if(gsize>=1)            cout << g.girl[gsize-1];        cout << endl;    }    return 0;}


0 0
原创粉丝点击