zoukankan      html  css  js  c++  java
  • 【BZOJ-2521】最小生成树 最小割

    2521: [Shoi2010]最小生成树

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 415  Solved: 242
    [Submit][Status][Discuss]

    Description

    Secsa最近对最小生成树问题特别感兴趣。他已经知道如果要去求出一个n个点、m条边的无向图的最小生成树有一个Krustal算法和另一个Prim的算法。另外,他还知道,某一个图可能有多种不同的最小生成树。例如,下面图 3中所示的都是图 2中的无向图的最小生成树:

     

    当然啦,这些都不是今天需要你解决的问题。Secsa想知道对于某一条无向图中的边AB,至少需要多少代价可以保证AB边在这个无向图的最小生成树中。为了使得AB边一定在最小生成树中,你可以对这个无向图进行操作,一次单独的操作是指:先选择一条图中的边 P1P2,再把图中除了这条边以外的边,每一条的权值都减少1。如图 4所示就是一次这样的操作:

     

    Input

    输入文件的第一行有3个正整数n、m、Lab分别表示无向图中的点数、边数、必须要在最小生成树中出现的AB边的标号。
    接下来m行依次描述标号为1,2,3…m的无向边,每行描述一条边。每个描述包含3个整数x、y、d,表示这条边连接着标号为x、y的点,且这条边的权值为d。
    输入文件保证1<=x,y<=N,x不等于y,且输入数据保证这个无向图一定是一个连通图。

    Output

    输出文件只有一行,这行只有一个整数,即,使得标号为Lab边一定出现最小生成树中的最少操作次数。

    Sample Input

    4 6 1
    1 2 2
    1 3 2
    1 4 3
    2 3 2
    2 4 4
    3 4 5

    Sample Output

    1

    HINT

    第1个样例就是问题描述中的例子。

    1<=n<=500,1<=M<=800,1<=D<10^6

    Source

    day2

    Solution

    水题

    首先考虑,选择一条边不变,其余边权-1;显然就相当于,选择一条边权+1,其余边不变

    要求选定边id一定在最小生成树上,考虑一下求最小生成树的过程Kruskal

    显然对这条边有影响的边是初始边权比他小的边,若id边一定加入到最小生成树中,也就是说,边权<=val[id]的边中,不存在能使x[id],y[id]的联通的边

    那么对于一条边x,使他不对id产生影响的最小代价是val[id]+1-val[x](使他边权变成恰大于id边权)

    那么显然最小化代价,用最小割处理即可

    把初始边权小于等于id的边相连,约束为val[id]+1-val[x],然后跑x[id]到y[id]的最小割即可

    Code

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    using namespace std;
    void Freopen () {freopen("build.in","r",stdin); freopen("build.out","w",stdout);}
    void Fclose() {fclose(stdin); fclose(stdout);}
    #define MAXM 1000010
    #define MAXN 1010
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    int N,M,id;
    struct RoadNode{int u,v,w,id;}road[MAXM];
    struct EdgeNode{int next,to,cap;}edge[MAXM<<1];
    int head[MAXN],cnt=1;
    void AddEdge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].cap=w;}
    void InsertEdge(int u,int v,int w) {AddEdge(u,v,w); AddEdge(v,u,0);}
    int h[MAXN],cur[MAXN],S,T;
    bool BFS()
    {
        queue<int>q;
        for (int i=S; i<=T; i++) h[i]=-1;
        q.push(S); h[S]=0;
        while (!q.empty())
            {
                int now=q.front(); q.pop();
                for (int i=head[now]; i; i=edge[i].next)
                    if (edge[i].cap && h[edge[i].to]==-1)
                        h[edge[i].to]=h[now]+1,q.push(edge[i].to);
            }
        return h[T]!=-1;
    }
    int DFS(int loc,int low)
    {
        if (loc==T) return low;
        int used=0,w;
        for (int i=cur[loc]; i; i=edge[i].next)
            if (edge[i].cap && h[edge[i].to]==h[loc]+1)
                {
                    w=DFS(edge[i].to,min(edge[i].cap,low-used));
                    edge[i].cap-=w,edge[i^1].cap+=w; used+=w;
                    if (edge[i].cap) cur[loc]=i;
                    if (used==low) return low;
                }
        if (!used) h[loc]=-1;
        return used;
    }
    #define INF 0x7fffffff
    int Dinic()
    {
        int re=0;
        while (BFS())
            {
                for (int i=S; i<=T; i++) cur[i]=head[i];
                re+=DFS(S,INF);
            }
        return re;
    }
    int D;
    void BuildGraph()
    {
        S=0,T=N+1;
        for (int i=1; i<=M; i++)
            if (road[i].w<=D)
                {
                    if (road[i].id!=id) 
                        InsertEdge(road[i].u,road[i].v,D+1-road[i].w),
                        InsertEdge(road[i].v,road[i].u,D+1-road[i].w);
                     else InsertEdge(S,road[i].u,INF),InsertEdge(road[i].v,T,INF);
                }
            else break;
    }
    bool cmp(RoadNode A,RoadNode B) {return A.w<B.w;}
    int main()
    {
        N=read(),M=read(),id=read();
        for (int i=1; i<=M; i++)
            road[i].u=read(),road[i].v=read(),road[i].w=read(),road[i].id=i;
        D=road[id].w;
        sort(road+1,road+M+1,cmp);
        BuildGraph();
        printf("%d
    ",Dinic());
        return 0;
    }
  • 相关阅读:
    ORA-28000: the account is locked-的解决办法
    j对ava序列化的学习理解
    Oracle数据库中的时间格式和java中时间格式的转换
    抽象类和接口的区别
    glVertexAttribPointer
    运算符重载
    lua回调时把函数当参数传递时需注意的事项
    visual studio 编译文件生成路径
    UITableView自定义Cell中,纯代码编程动态获取高度
    ASP.NET发送邮件(QQ发送)
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5770581.html
Copyright © 2011-2022 走看看