codeforces gym #101987B- Cosmetic Survey(floyd)
题目链接:
https://codeforces.com/gym/101987/my
题意:
顶点数为$n$,边数为$m$
求出每个点对$(a,b)$,$a$到$b$的最小路径的最大值
数据范围:
$1\leq n \leq 500$
$1\leq m \leq 1250000$
分析:
直接floyd处理
当时想的是用边来放缩S值,既然可以用边放缩,那么就可以用点放缩
AC代码:
#include<bits/stdc++.h> #define ll long long #define pii pair<int,int> using namespace std; const int maxn=500+7; int S[maxn][maxn]; int ma[maxn][maxn]; int sk[maxn],top,cnt,n,m; int main(){ scanf("%d %d",&m,&n); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ scanf("%d",&ma[i][j]); if(ma[i][j]==0)ma[i][j]=1e7; } for(int i=1;i<=m;i++){ for(int j=i+1;j<=m;j++){ int a=0,b=0; for(int k=1;k<=n;k++){ if(ma[k][i]<ma[k][j])a++; else if(ma[k][i]>ma[k][j])b++; } if(a>b)S[i][j]=a; else if(b>a)S[j][i]=b; } } for(int k=1;k<=m;k++){ for(int i=1;i<=m;i++){ for(int j=1;j<=m;j++){ if(S[i][k]==0||S[k][j]==0)continue; S[i][j]=max(S[i][j],min(S[i][k],S[k][j])); } } } for(int i=1;i<=m;i++){ int fla=1; for(int j=1;j<=m;j++){ if(i==j)continue; if(S[i][j]<S[j][i]){ fla=0; break; } } if(fla)sk[++top]=i; } for(int i=1;i<=top;i++){ printf("%d",sk[i]); if(i==top)printf("\n"); else printf(" "); } return 0; }