bzoj 2400: Spoj 839 Optimal Marks

来源:互联网 发布:淘宝 iphone att群 编辑:程序博客网 时间:2024/06/05 17:25

2400: Spoj 839 Optimal Marks

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 668  Solved: 248
[Submit][Status][Discuss]

Description

定义无向图中的一条边的值为:这条边连接的两个点的值的异或值。
定义一个无向图的值为:这个无向图所有边的值的和。
给你一个有n个结点m条边的无向图。其中的一些点的值是给定的,而其余的点的值由你决定(但要求均为非负数),使得这个无向图的值最小。在无向图的值最小的前提下,使得无向图中所有点的值的和最小。
 

Input

第一行,两个数n,m,表示图的点数和边数。
接下来n行,每行一个数,按编号给出每个点的值(若为负数则表示这个点的值由你决定,值的绝对值大小不超过10^9)。
接下来m行,每行二个数a,b,表示编号为a与b的两点间连一条边。(保证无重边与自环。)
 

Output

    第一行,一个数,表示无向图的值。
    第二行,一个数,表示无向图中所有点的值的和。
 

Sample Input

3 2
2
-1
0
1 2
2 3

Sample Output

2
2

HINT

数据约定

  n<=500,m<=2000

 

样例解释

    2结点的值定为0即可。



将异或操作分解到每一位,则变为0和1两种选择,且不同要付出1的代价,那么每一位做一个最小割


代码:

#include<iostream>#include<algorithm>#include<cstdlib>#include<cstdio>#include<cmath>#include<cstring>#include<string>#include<climits>#include<queue>#include<stack>#include<vector>#include<map>#include<set>#define N 10001#define M 2000020#define inf 1<<26using namespace std;typedef long long ll;inline ll read(){    ll x=0,f=1;char ch;    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;}ll n,m,s,t,c[N],uu[N],vv[N];ll head[N],pos=-1,cur[N];struct edge{ll to,next,c;}e[M];void add(ll a,ll b,ll c){pos++;e[pos].to=b,e[pos].c=c,e[pos].next=head[a],head[a]=pos;}void insert(ll a,ll b,ll c){add(a,b,c);add(b,a,0);}queue<ll>Q;bool vis[N];ll d[N];bool bfs(){    for(ll i=s;i<=t;i++)vis[i]=0,d[i]=-1;    Q.push(s);vis[s]=1,d[s]=0;    while(!Q.empty())    {ll u=Q.front();Q.pop();for(ll i=head[u];i!=-1;i=e[i].next){    ll v=e[i].to;    if(vis[v]||e[i].c<=0)continue;    d[v]=d[u]+1;vis[v]=1;Q.push(v);}    }return vis[t];}ll dfs(ll u,ll a){    if(u==t||!a)return a;    ll flow=0,f;    for(ll &i=cur[u];i!=-1;i=e[i].next)    {ll v=e[i].to;if(d[v]==d[u]+1&&(f=dfs(v,min(e[i].c,a)))>0){    flow+=f,a-=f;    e[i].c-=f,e[i^1].c+=f;    if(!a)break;}    }return flow;}ll dinic(){    ll ret=0;    while(bfs())    {for(ll i=s;i<=t;i++)cur[i]=head[i];ret+=dfs(s,inf);    }return ret;}void init(){pos=-1;memset(head,-1,sizeof(head));}bool build(){    init();bool f=0;    for(ll i=1;i<=n;i++)    {if(c[i]<0)continue;ll k=c[i]&1;f|=c[i]?1:0;c[i]>>=1;if(k)insert(s,i,inf);else insert(i,t,inf);    }    for(ll i=1;i<=m;i++)    {add(uu[i],vv[i],1);add(vv[i],uu[i],1);    }return f;}void dfs(ll u){vis[u]=1;for(ll i=head[u];i!=-1;i=e[i].next){ll v=e[i].to;if(vis[v]||e[i].c<=0)continue;dfs(v);}}ll val[N],ans,v[N];ll solve(){    ll ret=0,tme=1;    while(1)    {if(!build())break;ret+=tme*dinic();for(ll i=1;i<=n;i++)vis[i]=0;dfs(s);for(ll i=1;i<=n;i++)if(vis[i])val[i]+=tme;tme<<=1;    }return ret;}int main(){    n=read(),m=read();s=0,t=n+1;    for(ll i=1;i<=n;i++)v[i]=c[i]=read();    for(ll i=1;i<=m;i++)uu[i]=read(),vv[i]=read();    printf("%lld\n",solve());    for(ll i=1;i<=n;i++)    ans+=v[i]>=0?v[i]:val[i];    printf("%lld\n",ans);}


1 0