blockenemy
Time Limits: 1000 ms Memory Limits: 128000 KB
Description
你在玩电子游戏的时候遇到了麻烦。。。。。。 你玩的游戏是在一个虚拟的城市里进行,这个城市里有n个点,都从0~n-1编了号,每两个点之间有且仅有一条路径。现在,你的敌人到这个城市来踩点了!!!为了阻止他们更好的踩点, 你决定切断他们所有踩点人员的联系,使他们孤军作战,然后在各个击破。但是这就要切断某些街道,而你每切断一条路,市民就会产生相对的不满值,不满值越大,城市的和谐度就越小。所以你现在需要知道为了使踩点人员所在的点两两之间不联通所切断的边产生的最小不满值是多少?
Input
第一行一个数:n n<=50 以下n-1行,每行3个数 a,b,c 表示a点和b点之间有条路,切断这条路的不满值为c 以下若干行 每行一个数,表示踩点人员的位置
Output
一个数,最小不满值
Sample Input
5
1 0 1
1 2 2
0 3 3
4 0 4
3
2
4
Sample Output
4
不用多说了吧,将边按照边权为关键字,大到小排序,然后并查集,不用多说了吧。
Codes:
#include<cstdio>
#include<cstring>
#define fo(i,x,y) for(int i=x;i<=y;i++)
using namespace std;
int n,a[100][3],ans=0,fa[50],tot=0,top=0;
char num;
bool bz[50];
void insert(int,int,int);
void q(int,int);
int GetFather(int);
void swap(int &a,int &b){int c=a;a=b;b=c;}
int main()
{
scanf("%d",&n);
fo(i,1,n-1)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
insert(x,y,z);
tot+=z;
}scanf("\n");
q(1,top);
memset(bz,0,sizeof(bz));
for(;;)
{
num=getchar();
if(num<'0' || num>'9')break;
int x=num-'0';
for(;;)
{
num=getchar();
if(num<'0' || num>'9')break;
x+=x*9+(num-'0');
}
bz[x]=1;
}
fo(i,0,n-1)fa[i]=i;
fo(i,1,top)
{
int A=GetFather(a[i][1]),B=GetFather(a[i][0]);
if(!(bz[A]) || !(bz[B]))
{
if(bz[A] || bz[B])bz[B]=1;
fa[A]=B;
ans+=a[i][2];
}
}
printf("%d",tot-ans);
}
void insert(int x,int y,int z)
{
a[++top][0]=x;
a[top][1]=y;
a[top][2]=z;
}
void q(int h,int t)
{
int l=h,r=t,m=a[(h+t)>>1][2];
do{
while(a[l][2]>m)l++;
while(a[r][2]<m)r--;
if(l<=r)
{
swap(a[l][0],a[r][0]);
swap(a[l][1],a[r][1]);
swap(a[l++][2],a[r--][2]);
}
}while(l<=r);
if(h<r)q(h,r);if(l<t)q(l,t);
}
int GetFather(int x)
{
if(fa[x]==x)return x;
fa[x]=GetFather(fa[x]);
return fa[x];
}