[UVA 11865]Stream My Contest[最小ツリー図][二分答案]


タイトルリンク:[UVA 11865]Stream My Contest[最小ツリー図][二分答案]テーマ分析:サーバー(ノード0)からすべての大学のネットワークを構築し、実行可能なネットワークの中で、最小帯域幅が最大のネットワークに対応する帯域幅はいくらですか?テーマには2つの制限があります.
  • 大学間にはもともとネットワークがないので、ネットワークを構築する必要があり、一定の費用がかかり、最大予算はC元で、一方的です.
  • 大学間のネットワークには帯域幅があり、生成されたネットワークでは、トラフィックが最小帯域幅を超えてはいけません.そうしないと、指定されたユーザーに送信できません.

  • 问题解决の考え方:サーバーはすべてのノードに届いて、とても最小の木の形の図に合います==.しかし、本題には複数の制限条件があり、すべての生成ツリーの中で、最小エッジ権の最大値はいくらですか?この最小エッジ権を列挙して、この最小エッジ権より大きい最小ツリー図が存在するかどうかを列挙し、絶えず二分すればよい.个人感受:题目の第2の制限条件は半日见て、英语は急いで==を捕まえます.また、2つの制限条件の下の言葉もおかしいと思います.帯域幅を共有するなどのOrzの具体的なコードは以下の通りです.
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define ll long long
    using namespace std;
    
    const int INF = 0x7f7f7f7f;
    const int MAXN = 1e4 + 111;
    
    struct Edge{
        int u, v, band, cost;
    }edge[MAXN * 2];
    
    int n, m, C, pre[100], vis[100], newid[100], in[100];
    
    void add_edge(int cnt, int u, int v, int band, int cost)
    {
        edge[cnt + m].u = edge[cnt].u = u;
        edge[cnt + m].v = edge[cnt].v = v;
        edge[cnt + m].band = edge[cnt].band = band;
        edge[cnt + m].cost = edge[cnt].cost = cost;
    }
    
    bool zhuLiu(int rt, int V, int miband)
    {
        ll ret = 0;
        while (1)
        {
            for (int i = 0; i < V; ++i) in[i] = INF;
            for (int i = 0; i < m; ++i)
            {
                int u = edge[i].u, v = edge[i].v;
                if (u != v && edge[i].band >= miband && in[v] > edge[i].cost)
                {
                    in[v] = edge[i].cost;
                    pre[v] = u;
                }
            }
            for (int i = 0; i < V; ++i)
            {
                if (i != rt && in[i] == INF) return 0;
            }
    
            int cnt = 0;
            memset(newid, -1, sizeof newid);
            memset(vis, -1, sizeof vis);
            in[rt] = 0;
            for (int i = 0; i < V; ++i)
            {
                ret += in[i];
                int v = i;
                while (vis[v] != i && newid[v] == -1 && v != rt)
                {
                    vis[v] = i;
                    v = pre[v];
                }
                if (v != rt && newid[v] == -1)
                {
                    for (int u = pre[v]; u != v; u = pre[u]) newid[u] = cnt;
                    newid[v] = cnt++;
                }
            }
    
            if (cnt == 0) break;
            for (int i = 0; i < V; ++i)
                if (newid[i] == -1) newid[i] = cnt++;
    
            for (int i = 0; i < m; ++i)
            {
                int u = edge[i].u, v = edge[i].v;
                edge[i].u = newid[u];
                edge[i].v = newid[v];
                if (newid[u] != newid[v]) edge[i].cost -= in[v];
            }
            V = cnt;
            rt = newid[rt];
        }
        return (ret <= C);
    }
    
    int main()
    {
        int t, a, b, c, d; scanf("%d", &t);
        while (t --)
        {
            scanf("%d%d%d", &n, &m, &C);
            int mi = INF, mx = 0;
            for (int i = 0; i < m; ++i)
            {
                scanf("%d%d%d%d", &a, &b, &c, &d);
                add_edge(i, a, b, c, d);
                mi = min(mi, c);
                mx = max(mx, c);
            }
    
            if (!zhuLiu(0, n, mi)) printf("streaming not possible.
    "
    ); // else { int l = mi, r = mx; while (l <= r) { int mid = (l + r) >> 1; for (int i = 0; i < m; ++i) // , edge[i] = edge[i + m]; if (zhuLiu(0, n, mid)) l = mid + 1; else r = mid - 1; } printf("%d kbps
    "
    , r); } } return 0; }