题意:有n(1<=n<=2000)个城市,每个城市之间有不同的航空公司的航线k(1<=k<=200000)相连,每条航线有一定的费用,航空公司有
m(1<=m<=2000)个,现在想只保留一个航空公司,为了使得任意两个城市都能直接或者间接相连接,这样就需要收购其他公司掌控的一些航线,
但是需要花费相应的费用,问最少需要花费多少费用。
题解:这个题需要对最小生成树的边的性质有很好的理解,在最小生成树中任意一条边都是连接两个集合边权最小的一条边。首先枚举航空公司是肯定的,
那么怎样高效枚举出其他边呢?首先搞出最小生成树,然后然后枚举航空公司,然后再枚举在最小生成树中不属于当前航空公司的边即可,具体见代码。
Sure原创,转载请注明出处
#include <iostream> #include <cstdio> #include <algorithm> #include <memory.h> using namespace std; const int inf = 1 << 29; const int maxn = 2002; const int maxe = 200002; struct air { int id,u,v,c,p; bool operator < (const air &other) const { return p < other.p; } }ai[maxe]; struct node { int u,v,w; int next; }edge[maxe]; int head[maxn],father[maxn],ans[maxn],at[maxn]; int m,n,k,idx,top; int find(int u) { return (u == father[u]) ? father[u] : (father[u] = find(father[u])); } void init() { memset(head,-1,sizeof(head)); for(int i=1;i<=n;i++) { father[i] = i; } idx = top = 0; return; } void addedge(int num,int u,int v,int w) { edge[idx].u = u; edge[idx].v = v; edge[idx].w = w; edge[idx].next = head[num]; head[num] = idx++; return; } void read() { for(int i=0;i<k;i++) { ai[i].id = i+1; scanf("%d %d %d %d",&ai[i].u,&ai[i].v,&ai[i].c,&ai[i].p); addedge(ai[i].c , ai[i].u , ai[i].v , ai[i].p); } sort(ai , ai + k); return; } void kruskal() { for(int i=0;i<k;i++) { int x = find(ai[i].u); int y = find(ai[i].v); if(x != y) { ai[top++] = ai[i]; father[y] = x; } } return; } void inital(int st) { for(int i=1;i<=n;i++) { father[i] = i; } for(int i=head[st];i != -1;i=edge[i].next) { int x = find(edge[i].u); int y = find(edge[i].v); father[y] = x; } return; } void solve() { int sum = inf,bj,num; for(int i=1;i<=m;i++) { inital(i); int res = 0,c = 0; for(int j=0;j<top;j++) { int x = find(ai[j].u); int y = find(ai[j].v); if(x != y) { father[y] = x; res += ai[j].p; at[c++] = ai[j].id; } } if(res < sum) { sum = res; bj = i; num = c; for(int j=0;j<c;j++) { ans[j] = at[j]; } } } printf("%d %d %d\n",sum,bj,num); for(int i=0;i<num;i++) { printf("%d\n",ans[i]); } return; } int main() { while(~scanf("%d %d %d",&n,&m,&k)) { init(); read(); kruskal(); solve(); } return 0; }