sgu 298 差分约束(特定解)

来源:互联网 发布:linux 建网站 编辑:程序博客网 时间:2024/05/21 10:07

题目:http://acm.sgu.ru/problem.php?contest=0&problem=298
题意:

给定n个点m条约束。
下面输出 u v x 表示:
dis[u] - dis[v] >= x
然后建图就是 u->v 边权为-x
输出一个解满足 -10000<= dis[i] <= 10000。
若有多解输出一个 dis[n] - dis[1] 最小的解。

分析:

最短路得到最大解,最长路得到最小解,然后判断是否最大解全部不小于最小解。
因为要求dis[n]-dis[1]最小,那就令dis[n]为其最小解,dis[1]为其最大解,再spfa一遍就好。

有一个连等式:(规定求最短路的那个图为正向边和正权)正向边正权最短路的解的结构=反向边反权最长路解的结构=正向边反权最长路解的值取相反数之后的结构=反向边正权最短路解的值取相反数之后的结构。

代码:

const int N = 100000 + 9;struct Edge {    int v, w, next;};Edge edge[N], fedge[N];int head[N], fhead[N], d[N], fd[N], vis[N], num[N], n, cnt;void addedge (int u, int  v, int w) {    edge[cnt].v = v;    edge[cnt].w = w;    edge[cnt].next = head[u];    head[u] = cnt;    fedge[cnt].v = u;    fedge[cnt].w = w;    fedge[cnt].next = fhead[v];    fhead[v] = cnt++;}bool spfa (int head[], Edge edge[], int d[]) {    queue<int>q;    for (int i = 1; i <= n; i++) num[i] = 0, vis[i] = 1, q.push (i);    while (!q.empty() ) {        int u = q.front();        q.pop();        vis[u] = 0;        for (int i = head[u]; ~i; i = edge[i].next) {            if (d[edge[i].v] > d[u] + edge[i].w) {                d[edge[i].v] = d[u] + edge[i].w;                if (!vis[edge[i].v]) {                    q.push (edge[i].v);                    vis[edge[i].v] = 1;                    if (++num[edge[i].v] > n) return 0;                }            }        }    }    return 1;}int solve() {    for (int i = 1; i <= n; i++) d[i] = fd[i] = INF;    if (!spfa (head, edge, d) ) return 0;    if (!spfa (fhead, fedge, fd) ) return 0;    for (int i = 1; i <= n; i++)        if (d[i] < -fd[i]) return 0;    d[n] = -fd[n];    spfa (head, edge, d);    for (int i = 1; i < n; i++) printf ("%d ", d[i]);    printf ("%d\n", d[n]);    return 1;}int main() {    // freopen ("f.txt", "r", stdin);    int u, v, w, m;    while (~scanf ("%d%d", &n, &m) ) {        memset (head, -1, sizeof (head) );        memset (fhead, -1, sizeof (fhead) );        cnt = 0;        for (int i = 0; i < m; i++) {            scanf ("%d%d%d", &u, &v, &w);            addedge (u, v, -w);        }        if (!solve() ) puts ("-1");    }    return 0;}
0 0