GMOJ 6683. 我图呢 题解

简要の题意

求二分图 最大权 最大独立集 的方案。

\(n\le 500\)

思路

二分图最大权独立集很好做,二分图最大独立集也很好做。

考虑 双关键字排序 中第一个关键字无穷大于第二个关键字的优先级。

所以可以令点的数量带来的流量远大于权值带来的流量。

\(+\infty\) 即可。

构造方案直接按求割做。

CODE

#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#define reg register
#define uni unsigned
#define ll long long
using namespace std;
const int N=2010,FSIZE=1<<26;
const ll Inf=1000000000,INF=0x7f7f7f7f7f7f7f7f;
int n,m,h[N],a[N],last,w[N],d[N],cur[N],sum,cl[N];
ll b[N*N][3];
vector<int> T[N];
bool vis[N];
struct edge{
    int x,y;
}e[N*N];
char BuF[FSIZE],*InF=BuF;
template<typename T>void read(T &x){
    for(;47>*InF||*InF>58;++InF);
    for(x=0;47<*InF&&*InF<58;x=x*10+(*InF++^48));
}
void add(int x,int y,ll u){
    b[last][0]=a[x];
    b[a[x]=last][1]=y;
    b[last++][2]=u;
}
void Add(int x,int y,ll u){
    add(x,y,u);
    add(y,x,0);
}
bool bfs(){
    memset(w,127,sizeof(w));
    for(reg int h=0,t=w[0]=0;h<=t;h++){
        cur[d[h]]=a[d[h]];
        for(reg int i=a[d[h]];~i;i=b[i][0]){
            if(w[b[i][1]]>w[d[h]]+1&&b[i][2]){
                w[b[i][1]]=w[d[h]]+1;
                d[++t]=b[i][1];
            }
        }
    }
    return(w[n+1]<0x7f7f7f7f);
}
ll dfs(int now,ll flow){
    if(now==n+1||!flow) 
    return(flow);
    ll used=0,aflow;
    for(reg int &i=cur[now];~i;i=b[i][0]){
        if(w[b[i][1]]==w[now]+1&&b[i][2]&&(aflow=dfs(b[i][1],min(b[i][2],flow-used)))){
            b[i][2]-=aflow;
            b[i^1][2]+=aflow;
            used+=aflow;
            if(used==flow) break;
        }
    }
    if(used==0) w[now]=0;
    return(used);
}
ll dinic(){
    reg ll maxflow=0;
    for(;bfs();maxflow+=dfs(0,INF));
    return(maxflow);
}
void find(reg int x){
    vis[x]=1;
    for(reg int i=a[x];~i;i=b[i][0]){
        if(b[i][2]&&!vis[b[i][1]]) find(b[i][1]);
    }
}
void color(reg int x,reg int c){
    cl[x]=c;
    for(reg vector<int>::iterator i=T[x].begin();i!=T[x].end();++i)
        if(!~cl[*i]) color(*i,c^1);
}
int main(){
    freopen("graph.in","r",stdin);
    freopen("graph.out","w",stdout);
    fread(BuF,1,FSIZE,stdin);
    read(n);read(m);
    for(reg int i=0;i<n;read(h[++i]));
    memset(a,-1,sizeof(a));
    memset(cl,-1,sizeof(cl));
    for(reg int i=0;i<m;++i){
        read(e[i].x);read(e[i].y);
        T[e[i].x].push_back(e[i].y);
        T[e[i].y].push_back(e[i].x);
    }
    for(reg int i=1;i<=n;++i){
        sum+=h[i];
        if(!~cl[i]) color(i,0);
        if(cl[i]) Add(i,n+1,h[i]+Inf);
        else Add(0,i,h[i]+Inf);
    }
    for(reg int i=0;i<m;++i){
        if(cl[e[i].x]) Add(e[i].y,e[i].x,INF);
        else Add(e[i].x,e[i].y,INF);
    }
    ll ans=dinic();
    printf("%lld %lld\n",n-ans/Inf,sum-ans%Inf);
    find(0);
    for(int i=1;i<=n;++i) putchar(vis[i]^cl[i]?'1':'0');
    fclose(stdin);
    fclose(stdout);
    return(0);
}
上一篇:ACWING 854. Floyd求最短路(Floyd)未确认


下一篇:dijkstra STL 堆优化