题意:
现在有n个点,但是有k种类型,每种类型有ci个。现在有m条边连接这n个点,现在问对于每个type里面的点是不是可以cost为0到达自己同类型的点。如果可以输出Yes,并且找到每个类型间相互到达的最短距离。输出矩阵。
思路:
对于同一个类型的就用bfs,如果某个点能够到达跟它同类型的其他点,那么这个类型一定能够相互达到。然后缩点。用floyd就可以求解。
trick:
这道题目不难,但是后面在bfs的时候有个小地方没有注意到,在对于每个类型搜的时候flag要初始化。因为其他类型可能通过该类型的某个点到达flag被标记为1
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int c[600],flag[100010],startp[100010],sumc[600],belong[100010];
struct node{
int u,v,x;
};
node edge[300000];
int cmp(node a,node b){
return a.u<b.u;
}
int q[1000000];
int f[600][600];
int bfs(int sc,int ec){
int h=0,r=0;
q[h]=sc;
memset(flag,0,sizeof(flag));
flag[sc]=1;
while(h<=r){
int tmp=q[h];
//flag[tmp]=1;
int p=startp[tmp];
//printf("%d %d p:%d %d\n",sc,ec,p,tmp);
while(edge[p].u==tmp){
if(edge[p].x==0){
if(flag[edge[p].v]==0){
q[++r]=edge[p].v;
flag[edge[p].v]=1;
//printf("enter:%d\n",edge[p].v);
}
}
p++;
}
h++;
}
for(int i=sc;i<=ec;i++){
if(flag[i]==0){
//printf("wa:%d\n",i);
return 0;
}
}
return 1;
}
void floyd(int n){
for(int p=0;p<n;p++){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(f[i][j]>f[i][p]+f[p][j])
f[i][j]=f[i][p]+f[p][j];
}
}
}
}
main(){
int n,m,k;
while(scanf("%d%d%d",&n,&m,&k)!=-1){
memset(sumc,0,sizeof(sumc));
for(int i=0;i<k;i++){
scanf("%d",&c[i]);
if(i!=0){
sumc[i]=sumc[i-1]+c[i];
}
else{
sumc[i]=c[i];
}
}
for(int i=0;i<m;i++){
int cntu,cntv,cntx;
scanf("%d%d%d",&cntu,&cntv,&cntx);
edge[i].u=cntu-1;
edge[i].v=cntv-1;
edge[i].x=cntx;
edge[i+m].u=cntv-1;
edge[i+m].v=cntu-1;
edge[i+m].x=cntx;
}
sort(edge,edge+2*m,cmp);
memset(startp,-1,sizeof(startp));
for(int i=0;i<2*m;i++){
if(startp[edge[i].u]==-1){
startp[edge[i].u]=i;
}
}
/*for(int i=0;i<n;i++){
printf("sp:%d\n",startp[i]);
}
printf("wa");*/
int ans=1;
int spc=0,epc=-1;
memset(flag,0,sizeof(flag));
/*for(int i=0;i<2*m;i++){
printf("%d %d %d\n",edge[i].u,edge[i].v,edge[i].x);
}*/
for(int i=0;i<k;i++){
spc=epc+1;
epc=spc+c[i]-1;
//printf("%d %d\n",spc,epc);
if(bfs(spc,epc)==0){
//printf("se %d %d\n",spc,epc);
ans=0;
break;
}
}
//printf("wa");
if(ans==0){
printf("No\n");
}
else{
int spc=0,epc=-1;
for(int i=0;i<k;i++){
spc=epc+1;
epc=spc+c[i]-1;
for(int j=spc;j<=epc;j++){
belong[j]=i;
}
}
for(int i=0;i<k;i++){
for(int j=0;j<k;j++){
if(i==j){
f[i][j]=0;
}
else{
f[i][j]=10000000;
}
}
}
for(int i=0;i<2*m;i++){
if(f[belong[edge[i].u]][belong[edge[i].v]]>edge[i].x){
f[belong[edge[i].u]][belong[edge[i].v]]=edge[i].x;
}
}
floyd(k);
printf("Yes\n");
for(int i=0;i<k;i++){
for(int j=0;j<k-1;j++){
if(f[i][j]==10000000){
printf("-1 ");
}
else{
printf("%d ",f[i][j]);
}
}
if(f[i][k-1]==10000000){
printf("-1\n");
}
else{
printf("%d\n",f[i][k-1]);
}
}
}
}
}