L3-3 胜利者集合(天梯赛)
这个题知道是最大流 但是比赛的时候就是不知道怎么建图
#include <bits/stdc++.h>
using namespace std;
const int N = 1500, M = 10010, INF = 1e9;
int n, m, S, T;
struct Edge {
int to, nxt, flow;
}line[M];
int fist[N], idx, d[N], cur[N];
void add(int x, int y, int z) {
line[idx] = {y, fist[x], z}; fist[x] = idx ++;
line[idx] = {x, fist[y], 0}; fist[y] = idx ++;
}
bool bfs() {
queue<int> q;
memset(d, -1, sizeof d);
q.push(S), d[S] = 0, cur[S] = fist[S];
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = fist[u]; i != -1; i = line[i].nxt) {
int v = line[i].to;
if(d[v] == -1 && line[i].flow) {
d[v] = d[u] + 1;
cur[v] = fist[v];
if(v == T) return 1;
q.push(v);
}
}
}
return 0;
}
int find(int u, int limit) {
if(u == T) return limit;
int flow = 0;
for(int i = cur[u]; i != -1 && flow < limit; i = line[i].nxt) {
cur[u] = i;
int v = line[i].to;
if(d[v] == d[u] + 1 && line[i].flow) {
int t = find(v, min(line[i].flow, limit - flow));
if(!t) d[v] = -1;
line[i].flow -= t;
line[i ^ 1].flow += t;
flow += t;
}
}
return flow;
}
int dinic() {
int res = 0, flow;
while(bfs()) while(flow = find(S, INF)) res += flow;
return res;
}
int main() {
ios::sync_with_stdio(0); cin.tie(nullptr); cout.tie(nullptr);
cin >> n >> m;
vector<vector<int>> g(n, vector<int>(n, 0));
for(int i = 0; i < m; ++ i) {
int u, v;
cin >> u >> v;
u --, v --;
g[u][v] = 1, g[v][u] = -1;
}
S = n + (n - 2) * (n - 1) / 2;
T = S + 1;
int flag = 0;
for(int i = 0; i < n; ++ i) {
int win = n - 1;
for(int j = 0; j < n; ++ j)
if(g[i][j] == -1) win --;
idx = 0;
memset(fist, -1, sizeof fist);
int cur = n;
for(int j = 0; j < n; ++ j) {
if(j == i) continue;
for(int k = j + 1; k < n; ++ k) {
if(k == i) continue;
add(S, cur, 1);
if(g[j][k] == 0) {
add(cur, j, 1);
add(cur, k, 1);
}
if(g[j][k] == 1)
add(cur, j, 1);
if(g[j][k] == -1)
add(cur, k, 1);
cur ++;
}
}
bool ok = true;
for(int j = 0; j < n; ++ j) {
if(win - 1 - (g[j][i] > 0) < 0) {
ok = false;
break;
}
if(j != i)
add(j, T, win - 1 - (g[j][i] > 0));
}
if(!ok) continue;
if(dinic() == (n - 1) * (n - 2) / 2) {
if(flag) cout << ' ';
cout << i + 1;
flag = 1;
}
}
cout << '\n';
return 0;
}