codeforces 546E. Soldier and Traveling 网络流

来源:互联网 发布:最新网络术语 编辑:程序博客网 时间:2024/05/16 12:32

给出n个城市, 以及初始时每个城市的人数以及目标人数。初始时有些城市是相连的。 每个城市的人只可以待在自己的城市或走到与他相邻的城市, 相邻, 相当于只能走一条路。

如果目标状态不可达, 输出no, 否则输出每个城市的人都是怎么走的, 比如第一个城市有2个人走到了第二个城市, 1个人留在了第一个城市, 那么输出的第一行前两个数就是1, 2。

很明显的网络流, 输出那里写了好久...

首先判断能否可达, 如果初始状态的人数与目标状态不一样, 一定不可达, 其次, 如果建完图跑网络流的结果与所有目标城市人数的和不一样, 也不可达。

建图的话, 将一个城市拆成两个点, (u, u') 中间连边inf, 说明可以随便走, 源点和u相连, 权值为初始状态人数, u'与汇点相连, 人数为目标状态人数。 如果两个城市之间有路相连, 那么加边(u, v'), (v, u'), 权值为inf。

每个城市的人是怎么走的, 应该看反向边的流量, 如果边(v', u)的权值为x, 那么ans[u][v] = x。


#include<bits/stdc++.h>using namespace std;#define pb(x) push_back(x)#define ll long long#define mk(x, y) make_pair(x, y)#define lson l, m, rt<<1#define mem(a) memset(a, 0, sizeof(a))#define rson m+1, r, rt<<1|1#define mem1(a) memset(a, -1, sizeof(a))#define mem2(a) memset(a, 0x3f, sizeof(a))#define rep(i, a, n) for(int i = a; i<n; i++)#define ull unsigned long longtypedef pair<int, int> pll;const double PI = acos(-1.0);const double eps = 1e-8;const int mod = 1e9+7;const int inf = 1061109567;const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };const int maxn = 2e5;int q[maxn*2], head[maxn*2], dis[maxn/10], s, t, num, vis[105], val[205][205];struct node{    int to, nextt, c;    node(){}    node(int to, int nextt, int c):to(to), nextt(nextt), c(c){}}e[maxn*2];void init() {    num = 0;    mem1(head);}void add(int u, int v, int c) {    e[num] = node(v, head[u], c); head[u] = num++;    e[num] = node(u, head[v], 0); head[v] = num++;}int bfs() {    mem(dis);    dis[s] = 1;    int st = 0, ed = 0;    q[ed++] = s;    while(st<ed) {        int u = q[st++];        for(int i = head[u]; ~i; i = e[i].nextt) {            int v = e[i].to;            if(!dis[v]&&e[i].c) {                dis[v] = dis[u]+1;                if(v == t)                    return 1;                q[ed++] = v;            }        }    }    return 0;}int dfs(int u, int limit) {    if(u == t) {        return limit;    }    int cost = 0;    for(int i = head[u]; ~i; i = e[i].nextt) {        int v = e[i].to;        if(e[i].c&&dis[v] == dis[u]+1) {            int tmp = dfs(v, min(limit-cost, e[i].c));            if(tmp>0) {                e[i].c -= tmp;                e[i^1].c += tmp;                cost += tmp;                if(cost == limit)                    break;            } else {                dis[v] = -1;            }        }    }    return cost;}int dinic() {    int ans = 0;    while(bfs()) {        ans += dfs(s, inf);    }    return ans;}int main(){    int n, m, x, y, sum = 0, tmp = 0;    cin>>n>>m;    init();    s = 0, t = n*2+1;    for(int i = 1; i<=n; i++) {        scanf("%d", &x);        add(s, i, x);        tmp += x;    }    for(int i = 1; i<=n; i++) {        scanf("%d", &x);        add(i+n, t, x);        sum += x;        add(i, i+n, inf);    }    while(m--) {        scanf("%d%d", &x, &y);        add(x, y+n, inf);        add(y, x+n, inf);    }    int ans = dinic();    if(ans != sum||sum!=tmp) {        cout<<"NO"<<endl;        return 0;    }    cout<<"YES"<<endl;    for(int u = 1; u<=n; u++) {        for(int i = head[u]; ~i; i = e[i].nextt) {            int v = e[i].to;            if(v>n) {                val[u][v-n] = e[i^1].c;         //反向边流量            }        }    }    for(int i = 1; i<=n; i++) {        for(int j = 1; j<=n; j++) {            cout<<val[i][j]<<" ";        }        cout<<endl;    }    return 0;}




给出n个城市, 以及初始时每个城市的人数以及目标人数。初始时有些城市是相连的。 每个城市的人只可以待在自己的城市或走到与他相邻的城市, 相邻, 相当于只能走一条路。

如果目标状态不可达, 输出no, 否则输出每个城市的人都是怎么走的, 比如第一个城市有2个人走到了第二个城市, 1个人留在了第一个城市, 那么输出的第一行前两个数就是1, 2。

很明显的网络流, 输出那里写了好久...

首先判断能否可达, 如果初始状态的人数与目标状态不一样, 一定不可达, 其次, 如果建完图跑网络流的结果与所有目标城市人数的和不一样, 也不可达。

建图的话, 将一个城市拆成两个点, (u, u') 中间连边inf, 说明可以随便走, 源点和u相连, 权值为初始状态人数, u'与汇点相连, 人数为目标状态人数。 如果两个城市之间有路相连, 那么加边(u, v'), (v, u'), 权值为inf。

每个城市的人是怎么走的, 应该看反向边的流量, 如果边(v', u)的权值为x, 那么ans[u][v] = x。

阅读全文
0 0
原创粉丝点击