HDU - 2121 Ice_cream’s world II 无根最小树形图

HDU - 2121 :http://acm.hdu.edu.cn/showproblem.php?pid=2121

比较好的朱刘算法blog:https://blog.csdn.net/txl199106/article/details/62045479

题意:

  在一个有向图中,找一个点,使得这个点到其他点的距离和最小,输出距离和,和这个点的坐标。

思路:

  无根最小树形图,设所有的有向图的距离和为sum。自己建立一个虚拟的原点(n+1),向每一个节点连一条距离为sum+1的边。以n+1为根结点跑一遍最小树形图(复杂度O(VE)),如果求出的ans == -1 或者 ans >=2*(sum + 1),无解,因为这么大的ans,只可能用了两条我们自己建立的边。由于每条边的端点在跑最小树形图的时候会改变,所以记录这是第几条边rtt,结果就是rtt - m,代码中由减了1是因为原图是Base0的。

 

/*
* @Author: chenkexing
* @Date:   2018-09-05 11:05:14
* @Last Modified by:   chenkexing
* @Last Modified time: 2018-09-10 20:21:22
*/
#include <algorithm>
#include <iterator>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <stack>
#include <cmath>
#include <queue>
#include <list>
#include <map>
#include <set>
#include <cassert>
using namespace std;
//#pragma GCC optimize(3)
//#pragma comment(linker, "/STACK:102400000,102400000")  //c++
#define lson (l, mid, rt << 1)
#define rson (mid + 1, r, rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back
#define pq priority_queue

typedef long long ll;
typedef unsigned long long ull;

typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
typedef pair<int, pii> p3;

//priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '\n'

#define OKC                      \
    ios::sync_with_stdio(false); \
    cin.tie(0)
#define FT(A, B, C) for (int A = B; A <= C; ++A) //用来压行
#define REP(i, j, k) for (int i = j; i < k; ++i)
//priority_queue<int ,vector<int>, greater<int> >que;

const ll mos = 0x7FFFFFFF;  //2147483647
const ll nmos = 0x80000000; //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //18
const int mod = 1e9 + 7;
const double esp = 1e-8;
const double PI = acos(-1.0);

template <typename T>
inline T read(T &x) {
    x = 0;
    int f = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') f |= (ch == '-'), ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
    return x = f ? -x : x;
}

/*-----------------------showtime----------------------*/
const int maxm = 10009;
const int maxn = 1009;
struct Edge {
    int from, to, c;
} e[maxm];
int in[maxn], vis[maxn], pre[maxn], id[maxn];
int rtt;
int zhuliu(int root, int n, int m) {
    int res = 0;
    while (true) {
        memset(in, inf, sizeof(in));
        for (int i = 1; i <= m; i++) {
            if (e[i].from != e[i].to && e[i].c < in[e[i].to]) {
                pre[e[i].to] = e[i].from;
                in[e[i].to] = e[i].c;
                if (e[i].from == root) rtt = i;
            }
        }
        for (int i = 1; i <= n; i++) {
            if (i != root && in[i] == inf)
                return -1;
        }
        int tn = 0, v;
        memset(id, -1, sizeof(id));
        memset(vis, -1, sizeof(vis));

        in[root] = 0;
        for (int i = 1; i <= n; i++) {
            res += in[i];
            v = i;
            while (v != root && id[v] == -1 && vis[v] != i) {
                vis[v] = i;
                v = pre[v];
            }
            if (v != root && id[v] == -1) {
                id[v] = ++tn;
                for (int u = pre[v]; u != v; u = pre[u]) {
                    id[u] = tn;
                }
            }
        }
        if (tn == 0) break;
        for (int i = 1; i <= n; i++) {
            if (id[i] == -1) id[i] = ++tn;
        }

        for (int i = 1; i <= m; i++) {
            int v = e[i].to;
            e[i].to = id[e[i].to];
            e[i].from = id[e[i].from];
            if (e[i].to != e[i].from) {
                e[i].c -= in[v];
            }
        }

        n = tn;
        root = id[root];
    }
    return res;
}
int main() {
    int n, m, r;
    while (~scanf("%d%d", &n, &m)) {
        int sum = 0;
        for (int i = 1; i <= m; i++) {
            int u, v, c;
            scanf("%d%d%d", &u, &v, &c);
            u++, v++;
            e[i].from = u;
            e[i].to = v;
            e[i].c = c;
            sum += c;
        }
        sum++;
        for (int i = m + 1; i <= n + m; i++) {
            e[i].from = n + 1;
            e[i].to = i - m;
            e[i].c = sum;
        }

        int ans = zhuliu(n + 1, n + 1, n + m);
        // debug(ans);
        if (ans == -1 || ans - sum >= sum) {
            puts("impossible");
        } else {
            printf("%d %d\n", ans - sum, rtt - m - 1);
        }
        printf("\n");
    }

    return 0;
}

 

posted @ 2018-09-10 20:34  ckxkexing  阅读(177)  评论(0编辑  收藏  举报