woj 1124 最大流

来源:互联网 发布:一款网络赛车游戏 编辑:程序博客网 时间:2024/06/10 19:22

woj 1124

题意:有编号1~n共n只球队进行比赛,你的球队是第n号,每场比赛获胜的球队可获2分,输掉获0分,平局获1分,现在给出接下来的若干场对阵安排,问你的球队是否有机会联赛夺冠,即分数比其他队伍的分数都高。

思路:先让接下来的对阵中自己队伍相关的比赛全部获胜,如果这样依然有别的队伍分数高于自己,那么肯定无法夺冠,否则就开跑最大流。

这里的最大流建图就很简单了,源点到没有n号队伍参与的各比赛建边,容量为2;各球队到汇点建边,容量为score[n] - score[i] - 1;各比赛到其参与球队建边,容量为2。

满流的话就说明有可能夺得联赛冠军。

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;const int MAXN = 2000;//点数的最大值const int MAXM = 200000;//边数的最大值const int INF = 0x3f3f3f3f;struct Edge{    int to,next,cap,flow;}edge[MAXM];//注意是MAXMint tol;int head[MAXN];int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];void init(){    tol = 0;    memset(head,-1,sizeof(head));}//加边,单向图三个参数,双向图四个参数void addedge(int u,int v,int w,int rw=0){    edge[tol].to = v;edge[tol].cap = w;edge[tol].next = head[u];    edge[tol].flow = 0;head[u] = tol++;    edge[tol].to = u;edge[tol].cap = rw;edge[tol].next = head[v];    edge[tol].flow = 0;head[v]=tol++;}int sap(int start,int end,int N){    memset(gap,0,sizeof(gap));    memset(dep,0,sizeof(dep));    memcpy(cur,head,sizeof(head));    int u = start;    pre[u] = -1;    gap[0] = N;    int ans = 0;    while(dep[start] < N){        if(u == end){            int Min = INF;            for(int i = pre[u];i != -1; i = pre[edge[i^1].to])                if(Min > edge[i].cap - edge[i].flow)                        Min = edge[i].cap - edge[i].flow;            for(int i = pre[u];i != -1; i = pre[edge[i^1].to]){                edge[i].flow += Min;                edge[i^1].flow -= Min;            }            u = start;            ans += Min;            continue;        }        bool flag = false;        int v;        for(int i = cur[u]; i != -1;i = edge[i].next){            v = edge[i].to;            if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]){                flag = true;                cur[u] = pre[v] = i;                break;            }        }        if(flag){            u = v;            continue;        }        int Min = N;        for(int i = head[u]; i != -1;i = edge[i].next)            if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min){                Min = dep[edge[i].to];                cur[u] = i;            }        gap[dep[u]]--;        if(!gap[dep[u]])return ans;        dep[u] = Min+1;        gap[dep[u]]++;        if(u != start) u = edge[pre[u]^1].to;    }    return ans;}int score[MAXN], from[MAXN], to[MAXN];main() {    int n, m;    while(~scanf("%d %d", &n, &m)){        int maxn = 0;        for(int i = 1; i <= n; i++) {            scanf("%d", &score[i]);            if(i != n) maxn = max(maxn, score[i]);        }        int cnt = 0;        for(int i = 0; i < m; i++){            int u, v;            scanf("%d %d", &u, &v);            if(u == n || v == n) score[n] += 2;            else from[++cnt] = u, to[cnt] = v;        }        if(score[n] < maxn) {            puts("NO");            continue;        }        int src = 0, sink = n + cnt + 1;        init();        for(int i = 1; i <= cnt; i++) addedge(src, n + i, 2);        for(int i = 1; i < n; i++) addedge(i, sink, score[n] - 1 - score[i]);        for(int i = 1; i <= cnt; i++){            int u = from[i], v = to[i];            addedge(n + i, u, 2);            addedge(n + i, v, 2);        }        int maxflow = sap(src, sink, sink + 1);        if(maxflow == cnt * 2) puts("YES");        else puts("NO");    }}


0 0
原创粉丝点击