codeforces 400D Dima and Bacteria 并查集+floyd

时间:2023-03-10 06:43:27
codeforces 400D Dima and Bacteria 并查集+floyd

题目链接:http://codeforces.com/problemset/problem/400/D

题目大意:

  给定n个集合,m步操作,k个种类的细菌,

  第二行给出k个数表示连续的xi个数属于i集合。

  当某个种类之间两两交换的值都为0可行解,则输出所有种类之间交换的最小值;否则输出No

解题思路:当两点之间的距离为0时并查集到一个集合中,只需保证最终同一种类的细菌都在一个并查集中则是符合条件的可行解,再用FLOYD找最短路即可

 #include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define FFF 100005
int set[FFF];
int a[FFF];
int sw[][];
int cnt[];
int vis[FFF];
int n,k,m; int find(int x)
{
if(x==set[x])
return x;
else return set[x]=find(set[x]);
} void uion(int x,int y)
{
int l1=find(x);
int l2=find(y);
if(l1==l2)
return;
else
set[l2]=l1;
return;
} bool judge()
{
for(int l=;l<=k;l++)
{
int tmp=-;
for(int i=cnt[l-]+;i<=cnt[l];i++)
{
if(tmp==-)
tmp=find(i);
else
{
if(tmp!=find(i))
return false;
}
}
}
return true;
} void solve()
{
for(int l=;l<=k;l++)
{
for(int i=;i<=k;i++)
{
if(i!=l)
{
for(int j=;j<=k;j++)
{
if(j!=l&&j!=i)
{
if((sw[i][l]+sw[l][j]<sw[i][j]||sw[i][j]<)&&sw[i][l]>=&&sw[l][j]>=)
sw[i][j]=sw[i][l]+sw[l][j];
}
}
}
}
}
return;
} void print()
{
for(int i=;i<=k;i++)
{
sw[i][i]=;
for(int j=;j<=k;j++)
{
if(j==)
printf("%d",sw[i][j]);
else
printf(" %d",sw[i][j]);
}
cout<<endl;
}
return;
} int main()
{
int i,j,now;
scanf("%d%d%d",&n,&m,&k);
//n为点的总个数,m为边数,k为种类数
for(i=,now=;i<=k;i++)
{
int x;
scanf("%d",&x);
// 第i种细菌有x个
for( j=;j<x;j++)
{
a[j+now]=i;
set[j+now]=j+now;
}
now+=x;
cnt[i]=now-;
}
memset(sw,-,sizeof(sw));
// 两两种类之间的代价初始化成-1
while(m--)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(a[x]==a[y])
//属于同一种类
{
if(z==)
uion(x,y);
// 添入并查集
}
else
//不同种类的细菌
{
if(z==)
uion(x,y);
if(sw[a[x]][a[y]]==-)
// 该两类之间还没有交换代价
sw[a[x]][a[y]]=sw[a[y]][a[x]]=z;
else if(z<sw[a[x]][a[y]])
// 新的代价较小的情况
sw[a[x]][a[y]]=sw[a[y]][a[x]]=z;
}
}
if(!judge())
// 判断同种类的细菌之间是否为0
printf("No\n");
else
{
printf("Yes\n");
solve();
// floyd找最短路
print();
}
return ;
} /*
FLOYD
题目大意:给定n个集合,m步操作,k个种类的细菌,
第二行给出k个数表示连续的xi个数属于i集合。
当某个种类之间两两交换的值都为0可行解
解题思路:当两点之间的距离为0时并查集到一个集合中,
最终保证同种细菌都在一个并查集中
再用FLOYD找最短路*/