• hdu2242 (边双缩点)


    题意:给出n个点和m条无向边,每个点都有权值,要求去掉一条边,使得整个图变成两个连通块,并且两者的权值总和之差最小
    **思路:**首先去掉的边必定是桥,无桥的话对应无解,有桥的话,把边双都求出来缩点,然后dfs一遍统计答案

    #include<bits/stdc++.h>
    using namespace std;
    #define ls rt<<1
    #define rs (rt<<1)+1
    #define PI acos(-1)
    #define eps 1e-8
    #define ll long long
    #define fuck(x) cout<<#x<<"     "<<x<<endl;
    typedef pair<int,int> pii;
    const int inf=2e9;
    const int maxn=1e4+10;
    int d[4][2]={1,0,-1,0,0,1,0,-1};
    //int lowbit(int x){return x&-x;}
    //void add(int x,int v){while(x<=n)bit[x]+=v,x+=lowbit(x);}
    //int sum(int x){int ans=0;while(x>=1) ans+=bit[x],x-=lowbit(x);return ans;}
    inline ll read() {
        ll s = 0,w = 1;
        char ch = getchar();
        while(!isdigit(ch)) {
            if(ch == '-') w = -1;
            ch = getchar();
        }
        while(isdigit(ch))
            s = s * 10 + ch - '0',ch = getchar();
        return s * w;
    }
    inline void write(ll x) {
        if(x < 0)
            putchar('-'), x = -x;
        if(x > 9)
            write(x / 10);
        putchar(x % 10 + '0');
    }
    int gcd(int x,int y){
        return y==0?x:gcd(y,x%y);
    }
    
    
    struct edge{
        int u,v,nxt;
    }e[maxn<<2];
    int sz[maxn],bccv[maxn],val[maxn],head[maxn],dfn[maxn],low[maxn],bcc[maxn],bccn,cnt,n,m,sum,minn;
    stack<int>sta;
    vector<int>g[maxn];
    
    void dfs(int now,int fa){
        bool flag=0;
        dfn[now]=low[now]=++cnt;
        sta.push(now);
        for(int i=head[now];i!=-1;i=e[i].nxt){
            int v=e[i].v;
            if(!dfn[v]){
                dfs(v,now);
                low[now]=min(low[now],low[v]);
            }
            else
                if(v!=fa||flag)
                    low[now]=min(low[now],dfn[v]);
                else
                    flag=1;
        }
        if(low[now]==dfn[now]){
            bccn++;
            for(;;){
                int tmp=sta.top();sta.pop();
                bcc[tmp]=bccn;
                bccv[bccn]+=val[tmp];
                if(tmp==now) break;
            }
        }
    }
    
    void dfss(int now,int fa){
        sz[now]=bccv[now];
        for(int i=0;i<g[now].size();i++)
        {
            int v=g[now][i];
            if(v==fa||sz[v]!=0) continue;
            dfss(v,now);
            sz[now]+=sz[v];
            minn=min(minn,abs(sum-sz[v]-sz[v]));
        }
    }
    
    int main(){
        while(scanf("%d%d",&n,&m)!=EOF){
            int tmp=0;
            sum=cnt=bccn=0;
            minn=2e9;
            for(int i=1;i<=n;i++)
                head[i]=-1,dfn[i]=0,low[i]=0,sz[i]=0,bccv[i]=0,g[i].clear();
            for(int i=1;i<=n;i++)
                scanf("%d",&(val[i])),sum+=val[i];
            for(int i=1;i<=m;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                u++;v++;
                e[++tmp]={u,v,head[u]};
                head[u]=tmp;
                e[++tmp]={v,u,head[v]};
                head[v]=tmp;
            }
            for(int i=1;i<=n;i++)
                if(!dfn[i])
                    dfs(i,-1);
            for(int i=1;i<=tmp;i+=2){
                int u=e[i].u,v=e[i].v;
                if(bcc[u]!=bcc[v])
                    g[bcc[u]].push_back(bcc[v]),g[bcc[v]].push_back(bcc[u]);
            }
            dfss(1,-1);
            if(bccn==1){
                puts("impossible");
                continue;
            }
            write(minn);
            puts("");
        }
        return 0;
    }
    
  • 相关阅读:
    理解Python中的__init__和__new__
    Python内置数学函数
    Java实现邮箱验证
    Socket通信
    Jvm内存模型
    Java GC如何判断对象是否为垃圾
    ::符号
    替换特殊符号
    有意思的小知识
    有意思的小题目
  • 原文地址:https://www.cnblogs.com/eason9906/p/11754681.html
Copyright © 2020-2023  润新知