spoj839Optimal Marks

题意:略

怎样判断属于S,T集合。

如果从S出发到不了某点,该点出发也到不了T,那么割给那边都行。

如果S出发能到该点,该点出发也能到T,这种情况下dinic没结束。

只能从S到该点:只能分到S集。只能从该点到T,T集。

这题中两种都能分到时,假如S表示0,那贪心分到S。这样只要看它能不能到T,如果能到T,一定要选1,否则就选0.用类似SPFA的操作。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <cstring>
#include <map>
#include <queue>
#include <set>
#include <cassert>
#include <stack>
#include <bitset>
#define mkp make_pair
using namespace std;
const double EPS=1e-12;
typedef long long lon;
const lon SZ=510,SSZ=5005,APB=10000,one=1,INF=0x7FFFFFFF,mod=1000000007;
int n,m,src[SZ][SZ],knum,arr[SZ],S=507,T=508;
int ans[SZ],mp[SZ][SZ],dep[SZ];
bool vst[SZ];

void init()
{
    cin>>n>>m;
    for(int i=1;i<=m;++i)
    {
        int a,b;
        cin>>a>>b;
        src[a][b]=src[b][a]=1;
    }
    cin>>knum;
    for(int i=1;i<=knum;++i)
    {
        int a,b;
        cin>>a>>b;
        ans[a]=arr[a]=b;
        vst[a]=1;
    }
}

void add(int u,int v,int w)
{
    mp[u][v]=w;
}

bool bfs()
{
    memset(dep,0,sizeof(dep));
    dep[S]=1;
    queue<int> q;
    q.push(S);
    for(;q.size();)
    {
        int fr=q.front();
        q.pop();
        for(int i=1;i<=T;++i)
        {
            if(!dep[i]&&mp[fr][i])
            {
                dep[i]=dep[fr]+1;
                q.push(i);
                if(i==T)return 1;
            }
        }
    }
    return 0;
}

int dinic(int x,int flow)
{
    if(x==T)return flow;
    else
    {
        int rem=flow;
        for(int i=1;i<=T&&rem;++i)
        {
            if(dep[i]==dep[x]+1&&mp[x][i])
            {
                int tmp=dinic(i,min(rem,mp[x][i]));
                if(!tmp)dep[i]=0;
                rem-=tmp;
                mp[x][i]-=tmp,mp[i][x]+=tmp;
            }
        }
        return flow-rem;
    }
}

void build(int x)
{
    memcpy(mp,src,sizeof(src));
    for(int i=1;i<=n;++i)
    {
        if(vst[i])
        {
            if(arr[i]&(1<<x))
            {
                add(i,T,INF);
                add(T,i,0);
            }
            else
            {
                add(S,i,INF);
                add(i,S,0);
            }
        }
        else
        {
//            add(S,i,APB);
//            add(i,S,0);
//            add(i,T,APB);
//            add(T,i,0);
        }
    }
}

int v2[SZ];

void calc(int x)
{
    memset(v2,0,sizeof(v2));
    queue<int> q;
    for(int i=1;i<=n;++i)
    {
        if(mp[i][T])v2[i]=1,q.push(i);
    }
    for(;q.size();)
    {
        int fr=q.front();
        q.pop();
        for(int i=1;i<=n;++i)
        {
            if(!v2[i]&&mp[i][fr])
            {
                v2[i]=1;
                q.push(i);
            }
        }
    }
    for(int i=1;i<=n;++i)
    {
        //if(x==0)cout<<v2[i]<<endl;
        if(v2[i]&&!vst[i])ans[i]|=1<<x;
    }
}

void work()
{
    for(int i=0;i<31;++i)
    {
        build(i);
        int res=0;
        for(;bfs();)res+=dinic(S,INF);
        //cout<<"res: "<<res<<endl;
        calc(i);
    }
    for(int i=1;i<=n;++i)
    {
        cout<<ans[i]<<endl;
    }
}

void release()
{
    memset(vst,0,sizeof(vst));
    memset(src,0,sizeof(src));
    memset(ans,0,sizeof(ans));
}

int main()
{
    std::ios::sync_with_stdio(0);
    //freopen("d:\\1.txt","r",stdin);
    //cout<<(1<<31)<<endl;
    int casenum;
    cin>>casenum;
    //cout<<casenum<<endl;
    for(int time=1;time<=casenum;++time)
    //for(int time=1;scanf(" %s",ch+1)!=EOF;++time)
    {
        init();
        work();
        release();
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/gaudar/p/10749357.html