码迷,mamicode.com
首页 > 其他好文 > 详细

codevs 1218 疫情控制

时间:2016-08-06 15:45:38      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:

啊好烦这道题。。。。

基本思路网上都有。

注意的一点是在匹配的时候,如果有军队的来源没有被匹配到,那么就先匹配这个来源。(因为不花钱)。

不过数据好水。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxv 50050
#define maxe 100500
using namespace std;
int n,x,y,z,g[maxv],nume=0,m,c[maxv],anc[maxv][20],dis[maxv][20],l=1,r=0,disr[maxv],kr=0,fath[maxv];
int top=0,cnt=0;
bool vis[maxv],ret[maxv];
struct edge
{
    int v,w,nxt;
}e[maxe];
struct status
{
    int val,id;
}regis[maxv],stack[maxv];
bool cmp(status a,status b)
{
    return a.val<b.val;
}
void addedge(int u,int v,int w)
{
    e[++nume].v=v;
    e[nume].w=w;
    e[nume].nxt=g[u];
    g[u]=nume;
}
void dfs1(int x,int father)
{
    if (father==1) fath[x]=x;
    else if (x!=1) fath[x]=fath[father];
    for (int i=g[x];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if (v!=father)
        {
            anc[v][0]=x;dis[v][0]=e[i].w;
            disr[v]=disr[x]+e[i].w;r=max(r,disr[v]);
            dfs1(v,x); 
        }
    }
}
bool dfs2(int x,int father)
{
    if (vis[x]) return true;
    int cnt1=0,cnt2=0;
    for (int i=g[x];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if (v!=father)
        {
            cnt1++;
            if (dfs2(v,x)) cnt2++;
        }
    }    
    if ((cnt1==cnt2) && (cnt1!=0)) return true;
    return false;
}
void get_table()
{
    r+=kr;
    for (int i=1;i<=16;i++)
        for (int j=1;j<=n;j++)
        {
            anc[j][i]=anc[anc[j][i-1]][i-1];
            dis[j][i]=dis[j][i-1]+dis[anc[j][i-1]][i-1];
        }
}
int get_pnt(int x,int r)
{
    for (int i=16;i>=0;i--)
    {
        if (r>=dis[x][i])
        {
            r-=dis[x][i];
            x=anc[x][i];
        }
    }
    return x;
}
bool check(int x) 
{
    memset(vis,false,sizeof(vis));
    memset(ret,false,sizeof(ret));
    top=0;cnt=0;
    for (int i=1;i<=m;i++)
    {
        int v=c[i];
        if (disr[v]<x)
        {
            top++;
            stack[top].val=x-disr[v];
            stack[top].id=fath[v];
        }
        else if (disr[v]==x) vis[fath[v]]=true;
        else vis[get_pnt(v,x)]=true;
    }
    for (int i=g[1];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if (!dfs2(v,1))
        {
            regis[++cnt].val=disr[v];
            regis[cnt].id=v;
            ret[v]=true;
        }
    }
    if (top<cnt) return false;
    sort(stack+1,stack+top+1,cmp);
    sort(regis+1,regis+cnt+1,cmp);
    int p1=1,p2=1;
    while  ((p2<=cnt) && (p1<=top))
    {
        if (ret[stack[p1].id]) {ret[stack[p1].id]=false;p1++;}
        else
        {
            while ((!ret[regis[p2].id]) && (p2<=cnt)) p2++;
            while ((stack[p1].val<regis[p2].val) && (p1<=top)) p1++;
            if (p2==cnt+1) break;
            if (p1==top+1) break;
            ret[regis[p2].id]=false;p1++;p2++;
        }
    }
    for (int i=g[1];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if (ret[v]) return false;
    }
    return true;
}
int get_ans()
{
    int ans;
    while (l<=r)
    {
        int mid=(l+r)>>1;
        if (check(mid)) {ans=mid;r=mid-1;}
        else l=mid+1;
    }
    return ans;
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n-1;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        addedge(x,y,z);
        addedge(y,x,z);    
        if ((x==1) || (y==1)) kr=max(kr,z);
     }
    scanf("%d",&m);
    for (int i=1;i<=m;i++)
        scanf("%d",&c[i]);
    dfs1(1,0);
    get_table();
    printf("%d\n",get_ans());
    return 0;
}

 

codevs 1218 疫情控制

标签:

原文地址:http://www.cnblogs.com/ziliuziliu/p/5744071.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!