CF1061E政治E.政治解決レポート

CF1061E政治E.政治

問題は、そうDFS配列に置かサブツリーですので、木の性質を使用することを検討してください。

ツリーだけを考え、質問は各間隔を正確にするために選択されている\(K \)ヶ月。間隔が含まれているか支払わないかので範囲は、実際にはサブツリーですので。

だから我々は、それを開き、間隔を置い互いに独立したセクションの数を開くことができます。

質問は、各セットから選択するために、いくつかある、となり、\(K_I \)の数字は、消費電力を最大化します。

2つのツリー、各ポイントが選択または選択されていない、唯一の2つのツリーを考えると、単にコストの流れを考えます

\(Sは\)の各条件、フローのための仮想点を接続\(K_I \)の右辺\(0 \)点の偶数セットを選択することができ、この仮想点の各点、フロー\(1 \)右しばらく\(0 \)

同様にも、別のセット\(T \)

それを自分のポイントのいくつかについてのスプリット。


コード:

#include <cstdio>
#include <cctype>
#include <cstring>
#include <vector>
#include <algorithm>
const int SIZE=1<<21;
char ibuf[SIZE],*iS,*iT;
//#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
#define gc() getchar()
template <class T>
void read(T &x)
{
    int f=0;x=0;char c=gc();
    while(!isdigit(c)) f|=c=='-',c=gc();
    while(isdigit(c)) x=x*10+c-'0',c=gc();
    if(f) x=-x;
}
const int N=2020,M=5010;
int n,m,q0,q1,s,t,x,y;
int head[N],to[M],Next[M],edge[M],cost[M],cnt=1;
void add(int u,int v,int w,int c)
{
    to[++cnt]=v,edge[cnt]=w,cost[cnt]=c,Next[cnt]=head[u],head[u]=cnt;
    to[++cnt]=u,edge[cnt]=0,cost[cnt]=-c,Next[cnt]=head[v],head[v]=cnt;
}
int q[N*N],pre[N],dis[N],l,r;
bool spfa()
{
    memset(dis,-0x3f,sizeof dis);
    dis[q[l=r=1]=s]=0;
    while(l<=r)
    {
        int now=q[l++];
        for(int v,i=head[now];i;i=Next[i])
            if(edge[i]&&dis[v=to[i]]<dis[now]+cost[i])
            {
                dis[v]=dis[now]+cost[i];
                pre[q[++r]=v]=i;
            }
    }
    return dis[t]!=dis[0];
}
int sta[N],tot,id[N],siz[N],ned[N],eu[N],ev[N],toki;
std::vector <int> E[N];
void dfs1(int now,int fa)
{
    sta[++tot]=now;
    for(int v,i=0;i<E[now].size();i++)
        if((v=E[now][i])!=fa)
            dfs1(v,now),siz[now]+=siz[v];
    if(id[now])
    {
        if(ned[now]-siz[now]<0) toki=1;
        add(s,id[now],ned[now]-siz[now],0);
        siz[now]=ned[now];
        int k;
        do
        {
            k=sta[tot--];
            add(id[now],k,1,0);
        }while(k!=now);
    }
}
void dfs2(int now,int fa)
{
    sta[++tot]=now;
    for(int v,i=0;i<E[now].size();i++)
        if((v=E[now][i])!=fa)
            dfs2(v,now),siz[now]+=siz[v];
    if(id[now])
    {
        if(ned[now]-siz[now]<0) toki=1;
        add(id[now],t,ned[now]-siz[now],0);
        siz[now]=ned[now];
        int k;
        do
        {
            k=sta[tot--];
            add(k+n,id[now],1,0);
        }while(k!=now);
    }
}
int main()
{
    read(n),read(x),read(y);
    for(int w,i=1;i<=n;i++) read(w),add(i,i+n,1,w);
    m=2*n,s=++m,t=++m;
    for(int u,v,i=1;i<n;i++) read(u),read(v),E[u].push_back(v),E[v].push_back(u);
    for(int i=1;i<n;i++) read(eu[i]),read(ev[i]);
    read(q0);
    int mx;
    for(int a,i=1;i<=q0;i++)
    {
        read(a),read(ned[a]);
        id[a]=++m;
        if(a==x) mx=ned[a];
    }
    dfs1(x,0);
    memset(ned,0,sizeof ned);
    memset(id,0,sizeof id);
    memset(siz,0,sizeof siz);
    for(int i=1;i<=n;i++) E[i].clear();
    for(int i=1;i<n;i++) E[eu[i]].push_back(ev[i]),E[ev[i]].push_back(eu[i]);
    read(q1);
    for(int a,i=1;i<=q1;i++)
    {
        read(a),read(ned[a]);
        id[a]=++m;
        if(a==y&&mx!=ned[a]) toki=1;
    }
    dfs2(y,0);
    if(toki)
    {
        puts("-1");
        return 0;
    }
    int flow=0,ans=0;
    while(spfa())
    {
        ++flow;
        ans+=dis[t];
        int now=t;
        while(now!=s)
        {
            --edge[pre[now]];
            ++edge[pre[now]^1];
            now=to[pre[now]^1];
        }
    }
    if(flow==mx) printf("%d\n",ans);
    else puts("-1");
    return 0;
}

2019年6月1日

おすすめ

転載: www.cnblogs.com/butterflydew/p/10960322.html