POJ 2699 - The Maximum Number of Strong Kings(网络流‘最大流)

来源:互联网 发布:蜂窝数据栏下找不到app 编辑:程序博客网 时间:2024/05/16 01:50

题目:

http://poj.org/problem?id=2699

题意;

比赛中每个人的得分为他打败的人数,得分最高的人可称为 strongking,打败得分最高的人也可以成为SK,给出比赛中每个人的得分,从小到大排,求出最大可能的SK的人数。

思路:

好难想的建图> <

有人说:一般遇到竞赛图,网络流的可能性较大,因为竞赛图中的条件都与点的度数有关。

建图:左边是人(s,i,scor[i]),右边是比赛(j,t,1)。接着枚举答案(n<=10, 所以此处应该想到枚举),让后ans人成为SK,ans中的a,b,若scor[a] < scor[b],则建边(a,comp[a][b],1),因为a比b分少要成为Sk就要打败b。(comp记录的是比赛序号)。对于剩下的比赛,任意连(a,comp[a][b], 1),(b, comp[a][b], 1).当maxflow == (n*(n-1))/2时输出答案。

AC.

 

#include <iostream>#include <cstdio>#include <vector>#include <cstring>#include <string>#include <cmath>#include <algorithm>#include <queue>#include <sstream>using namespace std;const int INF = 1e9;string ss;int n, tot;int scor[15], v[2000], comp[15][15];struct edge {    int to, cap, rev;    edge(int tt, int cc, int rr) {        to = tt; cap = cc; rev = rr;    }};vector<edge> g[2000];int level[2000];int iter[2000];void addedge(int from, int to, int cap){    g[from].push_back(edge(to, cap, g[to].size()));    g[to].push_back(edge(from, 0, g[from].size()-1));}void bfs(int s){    memset(level, -1, sizeof(level));    queue<int> que;    level[s] = 0;    que.push(s);    while(!que.empty()) {        int v = que.front(); que.pop();        for(int i = 0; i < g[v].size(); ++i) {            edge &e = g[v][i];            if(e.cap > 0 && level[e.to] < 0) {                level[e.to] = level[v] + 1;                que.push(e.to);            }        }    }}int dfs(int v, int t, int f){    if(v == t) return f;    for(int &i = iter[v]; i < g[v].size(); ++i) {        edge &e = g[v][i];        if(e.cap > 0 && level[v] < level[e.to]) {            int d = dfs(e.to, t, min(f, e.cap));            if(d > 0) {                e.cap -= d;                g[e.to][e.rev].cap += d;                return d;            }        }    }    return 0;}int max_flow(int s, int t){    int flow = 0;    while(1) {        bfs(s);        if(level[t] < 0) return flow;        memset(iter, 0, sizeof(iter));        int f;        while( (f = dfs(s, t, INF)) > 0) {            flow += f;        }    }}void build(int s, int t, int num){    for(int i = 0; i <= 2000; ++i) g[i].clear();    memset(v, 0, sizeof(v));    for(int i = 1; i <= n; ++i) {        addedge(s, i, scor[i]);    }    for(int i = 1; i <= tot; ++i) {        addedge(i+n, t, 1);    }    for(int i = n-num+1; i <= n; ++i) {        for(int j = i + 1; j <= n; ++j) {            if(scor[i] < scor[j]) {                v[comp[i][j]] = 1;                addedge(i, comp[i][j]+n, 1);            }        }    }    for(int i = 1; i <= n; ++i) {        for(int j = i + 1; j <= n; ++j) {            if(!v[comp[i][j]]) {                addedge(i, comp[i][j]+n, 1);                addedge(j, comp[i][j]+n, 1);            }        }    }}int main(){    //freopen("in", "r", stdin);    int T;    scanf("%d", &T);    getchar();    while(T--) {        getline(cin, ss);        stringstream str(ss);        int a;        n = 0;        while(str>>a) {            scor[++n] = a;        }        tot = 0;        for(int i = 1; i <= n; ++i) {            for(int j = i+1; j <= n; ++j) {                comp[i][j] = ++tot;            }        }        int sum = (n*(n-1))/2;        int s = 0, t = tot + n + 1;        for(int i = n; i >= 1; --i) {            build(s, t, i);            if(max_flow(s, t) == sum) {                printf("%d\n", i);                break;            }        }    }    return 0;}

0 0
原创粉丝点击