1. 程式人生 > >[CF] 986 A. Fair

[CF] 986 A. Fair

就是 nim 連通圖 stream 無向連通圖 做的 clu gin printf

http://codeforces.com/problemset/problem/986/A

n個點的無向連通圖,每個點有一個屬性,求每個點到s個不同屬性點的最短距離

依稀記得那天晚上我和Menteur-Hxy探討這道題如何不可做的樣子

直觀想法當然是每個點出發bfs,找到s個就停止,但這最差是n^2的,不能接受!

解法是多源廣搜,註意到貨物種類非常小(<=100),所以可以求出每個點獲得每種貨物的最短距離。

做法是進行k次bfs,對於第i次,起點st是每個種類為i的點,廣搜的性質決定了她們的平行關系。

這樣就可以求出每種貨物到每個點的距離,換言之,就是每個點獲得每種貨物的代價(最小)

然後對於每個點,答案就是最小的s個啦

無向圖註意開兩倍邊

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>

using namespace std;

const int MAXN=100005;

inline int rd(){
  int ret=0,f=1;char c;
  while(c=getchar(),!isdigit(c))f=c==
-?-1:1; while(isdigit(c))ret=ret*10+c-0,c=getchar(); return ret*f; } struct Edge{ int next,to; }e[MAXN<<1]; int ecnt,head[MAXN]; inline void add(int x,int y){ e[++ecnt].to = y; e[ecnt].next = head[x]; head[x] = ecnt; } int dis[MAXN][102],typ[MAXN]; //dis[i][j] - the minimum cost for town i to get the j-th goods
int n,m,k,s; queue<int> Q; void bfs(int x){ for(int i=1;i<=n;i++) if(typ[i]==x) Q.push(i),dis[i][x]=0; while(!Q.empty()){ int top=Q.front();Q.pop(); for(int i=head[top];i;i=e[i].next){ int v=e[i].to; if(dis[v][x]>dis[top][x]+1){ dis[v][x]=dis[top][x]+1; Q.push(v); } } } } void init(){ memset(dis,0x3f,sizeof(dis)); } vector<int> V; int main(){ n=rd();m=rd();k=rd();s=rd(); init(); for(int i=1;i<=n;i++) typ[i]=rd(); int x,y,w; for(int i=1;i<=m;i++){ x=rd();y=rd(); add(x,y);add(y,x); } for(int i=1;i<=k;i++) bfs(i); int ret=0; for(int i=1;i<=n;i++){ V.clear(); for(int j=1;j<=k;j++) V.push_back(dis[i][j]); sort(V.begin(),V.end()); ret=0; for(int j=0;j<s;j++) ret+=V[j]; printf("%d ",ret); } return 0; }

[CF] 986 A. Fair