T 1 T 2 T1T2 T1T2在上一篇博客里写过了
T 3 T3 T3没有完全懂,就把 T 4 T4 T4写出来了
题面的 m d md md好像炸了呜呜呜
首先可以想到的做法是先
O
(
n
2
)
O(n^2)
O(n2)枚举两个人,再
O
(
n
2
)
O(n^2)
O(n2)枚举他们所选的课程,但是总复杂度为
O
(
n
4
)
O(n^4)
O(n4)无法通过此题。不妨先
f
l
o
y
d
floyd
floyd求出最短路,再通过预处理重复的即可
代码:
#include <bits/stdc++.h>
#define int long long
#define ll long long
#define F(i,a,b) for(int i = (a);i<=(b);i++)
#define R register
using namespace std;
inline int read() {R int x=0,t=1;R char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*t;}
const int N=3e2+10;
int n,K,k[N],flag[N][N],a[N][N],w[N],dis[N][N];
vector<int>g[N];
inline void solve()
{
n=read(),K=read();
F(i,1,K)
F(j,1,K) dis[i][j]=1e9;
F(i,1,K) dis[i][i]=0;
F(i,1,n)
{
k[i]=read();
F(j,1,k[i])
{
a[i][j]=read();
g[a[i][j]].push_back(i);
}
for(int k1=1;k1<=k[i];k1++){
for(int k2=1;k2<=k[i];k2++){
flag[a[i][k1]][a[i][k2]]=1;
}
}
}
for(int i = 1;i<=K;i++){
for(int j = 1;j<=K;j++){
if(!flag[i][j]) continue;
memset(w,0,sizeof w);
int tot=0;
for(int k1=0;k1<g[i].size();k1++) w[g[i][k1]]=1;
for(int k1=0;k1<g[j].size();k1++){
if(!w[g[j][k1]]) tot++;
}
dis[i][j]=min(dis[i][j],tot);
}
}
F(k1,1,K){
F(i,1,K){
F(j,1,K){
dis[i][j]=min(dis[i][j],dis[i][k1]+dis[k1][j]);
}
}
}
F(i,1,n){
F(j,1,K) w[j]=1e9;
F(j,1,k[i]){
w[a[i][j]]=g[a[i][j]].size();
}
F(k1,1,K){
F(k2,1,K){
w[k2]=min(w[k2],w[k1]+dis[k1][k2]);
}
}
F(j,1,n){
int ans=1e9;
if(i==j) ans=0;
F(t,1,k[j]){
ans=min(ans,w[a[j][t]]);
}
if(ans==1e9) ans=-1;
cout << ans << ' ';
}
puts("");
}
}
signed main()
{
freopen("D.in","r",stdin);
freopen("D.out","w",stdout);
solve();
return 0;
}