ACM/ICPC World Finals 2013 C Surely You Congest

来源:互联网 发布:微博客户端mac 编辑:程序博客网 时间:2024/04/20 02:28

题目大意

给定一个图,给你n个人的起点,同时出发,不允许两个人同时通过同一条边的同一个方向,所有人必须走最短路径,问满足这种情况的最多的人数。

解答

首先先用SPFA求出最短路图,然后对每一个到终点相同距离的人拎出来做网络流,然后将每次求出的最大流求和就可以了。

附上AC代码:

#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <queue>#include <algorithm>using namespace std;const int MAXM = 150005;const int MAXN = 100000;const int oo = 2147483647;inline int getint(){    int ans = 0;    char w = getchar();    while (w < '0' || w > '9')        w = getchar();    while ('0' <= w && w <= '9') {        ans = ans * 10 + w - '0';        w = getchar();    }    return ans;}class Edge{    public:        int to;        int len;        int next;};class PEdge{    public:        int to;        int from;        int len;        int next;};Edge es[MAXM];Edge ces[MAXN];int head[MAXN];int h[MAXN];int ch[MAXN];PEdge ee[MAXM];int person[MAXN];int ph[MAXN];int et = -1;int cet = -1;int pet = -1;int st, th;int fl[MAXN];bool vis[MAXN];int dis[MAXN];int n, m, c;bool cmp(int a, int b){    return dis[a] < dis[b];}void addEdge(int u, int v){    cet++;    ces[cet].to = v;    ces[cet].len = 1;    ces[cet].next = ch[u];    ch[u] = cet;    cet++;    ces[cet].to = u;    ces[cet].len = 0;    ces[cet].next = ch[v];    ch[v] = cet;}void add(int u, int v, int l){    pet++;    ee[pet].to = v;    ee[pet].from = u;    ee[pet].len = l;    ee[pet].next = ph[u];    ph[u] = pet;    pet++;    ee[pet].to = u;    ee[pet].from = v;    ee[pet].len = l;    ee[pet].next = ph[v];    ph[v] = pet;}void newEdge(int u, int v){    et++;    es[et].to = v;    es[et].len = 1;    es[et].next = h[u];    h[u] = et;    et++;    es[et].to = u;    es[et].len = 0;    es[et].next = h[v];    h[v] = et;}bool bfs(){    memset(fl, 0, sizeof(fl));    queue<int> ser;    fl[st] = 1;    ser.push(st);    int root;    bool flag = false;    while (!ser.empty()) {        root = ser.front();        ser.pop();        for (int i = h[root]; i != -1; i = es[i].next)            if (es[i].len && !fl[es[i].to]) {                fl[es[i].to] = fl[root] + 1;                ser.push(es[i].to);                if (es[i].to == th)                    flag = true;            }    }    return flag;}int dfs(int x, int flow){    if (x == th)        return flow;    int cflow = flow;    int ret;    for (int &i = head[x]; i != -1; i = es[i].next)        if (es[i].len && fl[es[i].to] == fl[x]+1) {            ret = dfs(es[i].to, min(flow, es[i].len));            es[i].len -= ret;            es[i^1].len += ret;            flow -= ret;            if (!flow)                return cflow;        }    return cflow-flow;}int dinic(){    int ans = 0;    while(bfs()) {        for (int i = 1; i <= n+2; i++)            head[i] = h[i];        ans += dfs(st, oo);    }    return ans;}void SPFA(int s = 1){    queue<int> ser;    memset(vis, 0, sizeof(vis));    for (int i = 1; i <= n; i++)        dis[i] = oo;    dis[s] = 0;    ser.push(s);    int root;    vis[s] = true;    while(!ser.empty()) {        root = ser.front();        ser.pop();        for (int i = ph[root]; i != -1; i = ee[i].next) {            if (dis[ee[i].to] > dis[root]+ee[i].len) {                dis[ee[i].to] = dis[root]+ee[i].len;                if (!vis[ee[i].to]) {                    ser.push(ee[i].to);                    vis[ee[i].to] = true;                }            }        }        vis[root] = false;    }}void check(){    for (int i = 0; i < m*2; i++)        if (dis[ee[i].to] == dis[ee[i].from] + ee[i].len) {            addEdge(ee[i].to, ee[i].from);        }}void readin(){    memset(h, -1, sizeof(h));    memset(ch, -1, sizeof(ch));    memset(ph, -1, sizeof(ph));    n = getint();    m = getint();    c = getint();    //scanf("%d %d %d", &n, &m, &c);    int x, y, z;    for (int i = 0; i < m; i++) {        //scanf("%d %d %d", &x, &y, &z);        x = getint();        y = getint();        z = getint();        add(x, y, z);    }    SPFA();    check();    for (int i = 0; i < c; i++) {        //scanf("%d", &x);        person[i] = getint();    }    sort(person, person+c, cmp);    th = 1;    st = n+2;}void setUp(){    et = cet;    for (int i = 0; i <= n+2; i++)        h[i] = ch[i];    for (int i = 0; i <= cet; i++)        es[i] = ces[i];}void work(){    int ans = 0;    int tmp = dis[person[0]];    setUp();    for (int i = 0; i < c; i++) {        if (dis[person[i]] == tmp) {            newEdge(st, person[i]);        } else {            ans += dinic();            setUp();            newEdge(st, person[i]);            tmp = dis[person[i]];        }    }    ans += dinic();    printf("%d", ans);}int main(){    //freopen("input.in", "r", stdin);    readin();    work();    return 0;}
0 0
原创粉丝点击