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

中转站

时间:2016-05-07 08:54:51      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define efo(i,u) for(int i=last[u];i;i=next[i])
using namespace std;
typedef long long ll;
const int N=100010,M=N*2,INF=2147483647;
struct node
{
    int w,bz,p;
}a[N];
int n,tot,val,num,rt,to[M],next[M],wei[M],last[N],sum[N],lyd[N][2],lh[19][N];
ll ans;
bool bz[N],p[N*2];
void link(int u,int v,int w)
{
    to[++tot]=v;
    wei[tot]=w;
    next[tot]=last[u];
    last[u]=tot;
}
int getsum(int v,int from)
{
    int t=1;
    efo(i,v)
    {
        int u=to[i];
        if(u==from || bz[u]) continue;
        t+=getsum(u,v);
    }
    return t;
}
void findrt(int v,int from,int tot)
{
    int mx=0;
    sum[v]=1;
    efo(i,v)
    {
        int u=to[i];
        if(u==from || bz[u]) continue;
        findrt(u,v,tot);
        sum[v]+=sum[u];
        mx=max(mx,sum[u]);
    }
    int t=max(mx,tot-mx);
    if(t<val) val=t,rt=v;
}
void dfs(int v,int from,int w,int S)
{
    a[++num].w=w,a[num].bz=S;
    a[num].p=p[N+a[num].w];
    p[N+w]=1;
    efo(i,v)
    {
        int u=to[i];
        if(u==from || bz[u]) continue;
        dfs(u,v,w+wei[i],S);
    }
    p[N+w]=0;
}
void divide(int v,int from)
{
    int tot=getsum(v,from);
    val=INF;
    findrt(v,from,tot);
    bz[rt]=1;
    num=0;
    efo(i,v)
    {
        int u=to[i];
        if(u==from || bz[u]) continue;
        dfs(u,from,wei[i],u);
    }
    memset(lyd,0,sizeof(lyd));
    memset(lh,0,sizeof(lh));
    int t=0;
    fo(i,1,num)
    {
        int w=N+a[i].w;
        if(a[i].bz!=a[i-1].bz) t++;
        if(a[i].p && a[i].w==0) ans++;
        lyd[w][a[i].p]++;
        lh[t][w]++;
    }
    t=0;
    ll x=0;
    fo(i,1,num)
    {
        int w=N+a[i].w,nw=N-a[i].w;
        if(a[i].bz!=a[i-1].bz) t++;
        if(a[i].p) x+=lyd[nw][0]+lyd[nw][1]-lh[t][nw];
        else x+=lyd[nw][1]-lh[t][nw];
    }
    ans+=x/2;
    efo(i,rt)
    {
        int u=to[i];
        if(u==from || bz[u]) continue;
        divide(u,rt);
    }
}
int main()
{
    freopen("3234.in","r",stdin);
    //freopen("3234.out","w",stdout);
    int u,v,w;
    scanf("%d",&n);
    fo(i,1,n-1)
    {
        scanf("%d %d %d",&u,&v,&w);
        if(!w) w=-1;
        link(u,v,w),link(v,u,w);
    }
    divide(1,0);
    printf("%lld",ans);
    return 0;
}

中转站

标签:

原文地址:http://blog.csdn.net/lyd_7_29/article/details/51333500

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