codeforces round 485 D 图dp
题意:
无向连通图,n点,m边。
k种货物,每个节点存放一种货物。不过k种货物你只需要s种。
依次输出以每个节点为起始点要得到s种货物所需要的最少步数。(每条边的权值为1).
思路:
n和m都是1e5,但是k为100。可以想一种遍历k的算法--->对于每一种颜色,算出每个点到它要的最小值。
dp[i][j]:i为点,j为颜色
k遍bfs即可。
代码:
#include <bits/stdc++.h> using namespace std; #define ll long long const int maxn = 1e5+7; const int inf=0x3f3f3f3f; int n,m,k,s; int u,v; int a[maxn]; vector<int> co[105]; struct edge{ int v; int next; }e[maxn*2]; int total=0; int head[maxn]; void addedge(int u, int v){ total++; e[total].v=v; e[total].next=head[u]; head[u]=total; } struct node{ int u; int len; }; int vis[maxn]; node temp; int dp[maxn][105]; void bfs(int type){ if(co[type].size()==0)return; for(int i=1;i<=n;i++){ vis[i]=0; dp[i][type]=inf; } queue<node> que; for(int i=0;i<co[type].size();i++){ temp.u=co[type][i];temp.len=0; dp[temp.u][type]=0; que.push(temp); vis[temp.u]=1; } while(que.size()){ node top=que.front();que.pop(); u=top.u; for(int i=head[u];i;i=e[i].next){ int v=e[i].v; if(vis[v])continue; dp[v][type]=min(dp[v][type], dp[u][type]+1); temp.u=v;temp.len=dp[v][type]; vis[v]=1; que.push(temp); } } } int main() { freopen("in.txt","r",stdin); scanf("%d%d%d%d",&n,&m,&k,&s); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); co[a[i]].push_back(i); } while(m--){ scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } for(int i=1;i<=k;i++) bfs(i); int ans; for(int i=1;i<=n;i++){ sort(dp[i]+1, dp[i]+1+k); ans=0; for(int j=1;j<=s;j++){ ans+=dp[i][j]; } printf("%d ",ans); } }

浙公网安备 33010602011771号