哈理工oj 1360-Leyni的国家III解题报告
链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1360
这道题的题意是说,一个图中的点相互连接,但是不同的城市之间的连线的警戒等级是不一样的,由低到高分为a,b,c三级,两个点之间可能有多条路径连接,每条单独的路径的警戒级别是这条路径上的警戒级别最高的那条路的级别,而两个城市之间的警戒级别是所有路径当中警戒级别最低级别,这是一道比较难的并查集的问题,关键就在于是什么时候该用哪一个级别的合并函数将两个点合并,很明显如果a,b两点之间有一条级别为a的路相连,那么b和所有与a相连的点中都有一条等级为a的路径相连,而如果a,b之间的连接等级为b那么所有与a相连的等级<=b的点与b点都有一条b等级的路径连接,而b与所有与a相连的等级大于b的点之间都有一条等级大于b的路径连接,对c同理
View Code
#include<stdio.h> #include<string.h> #define N 100005 int a[3][N]; int n; void init() { int i; for(i=1;i<=n;i++) a[0][i]=a[1][i]=a[2][i]=i; } int find0(int i) { int r=i; while(r!=a[0][r]) r=a[0][r]; int t; while(i!=a[0][i]) { t=a[0][i]; a[0][i]=r; i=t; } return r; } int find1(int i) { int r=i; while(r!=a[1][r]) r=a[1][r]; int t; while(i!=a[1][i]) { t=a[1][i]; a[1][i]=r; i=t; } return r; } int find2(int i) { int r=i; while(r!=a[2][r]) r=a[2][r]; int t; while(i!=a[2][i]) { t=a[2][i]; a[2][i]=r; i=t; } return r; } void uni0(int i,int j) { int t1=find0(i); int t2=find0(j); if(t1!=t2) a[0][t2]=t1; } void uni1(int i,int j) { int t1=find1(i); int t2=find1(j); if(t1!=t2) a[1][t2]=t1; } void uni2(int i,int j) { int t1=find2(i); int t2=find2(j); if(t1!=t2) a[2][t2]=t1; } int main() { int m,q; int t; scanf("%d",&t); int t1,t2; char s[2]; int i,j,k; while(t--) { scanf("%d%d%d",&n,&m,&q); init(); for(i=0;i<m;i++) { scanf("%d%d%s",&t1,&t2,s); int temp=s[0]-'a'; if(temp==0)//搞清楚对应不同的情况应该用的合并函数 { uni0(t1,t2); uni0(find1(t1),t2); uni0(find2(t1),t2); } else if(temp==1) { uni1(t1,t2); uni1(find2(t1),t2); uni0(find0(t1),t2); } else { uni2(t1,t2); uni1(find1(t1),t2); uni0(find0(t1),t2); } } for(i=0;i<q;i++) { scanf("%d%d",&t1,&t2); if(find2(t1)==find2(t2)) { printf("c\n"); continue; } if(find1(t1)==find1(t2)) { printf("b\n"); continue; } if(find0(t1)==find0(t2)) { printf("a\n"); continue; } printf("-1\n"); } } return 0; }