Time Limit: 5000MS | Memory Limit: 10000K | |
Total Submissions: 7381 | Accepted: 2567 |
Description
Input
Output
Sample Input
10 Alphonzo Bernardo 32 Alphonzo Park 57 Alphonzo Eduardo 43 Bernardo Park 19 Bernardo Clemenzi 82 Clemenzi Park 65 Clemenzi Herb 90 Clemenzi Eduardo 109 Park Herb 24 Herb Eduardo 79 3
Sample Output
Total miles driven: 183
********************************************************
题目大意:见黑书P300。
解体思路:见黑书P300。度限制最小生成树,按照黑书的意思拍代码即可。
//#pragma comment(linker, "/STACK:65536000") #include <map> #include <stack> #include <queue> #include <math.h> #include <vector> #include <string> #include <fstream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> #define N 1005 #define M 200005 #define E #define inf 0x3f3f3f3f #define dinf 1e10 #define linf (LL)1<<60 #define LL long long #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; int n,m,k; int dis[N],vis[N],pd[N],pv[N],pg[N]; map<string,int>hash; int eid,head[N],nxt[M],ed[M],val[M],flag[M]; struct Node//双重用处 { int ed,v,id; bool operator<(const Node & a)const { return v>a.v; } Node(int a,int b):ed(a),v(b){} Node(int a,int b,int c):ed(a),v(b),id(c){} }; priority_queue<Node>que;//prim优先队列 vector<Node>gra[N];//构建的最小生成树森林 void addedge(int s,int e,int v) { ed[eid]=e;val[eid]=v;flag[eid]=0; nxt[eid]=head[s];head[s]=eid++; } //在每加一条V0带Vi的一条边时,对其他点更新 void dfs(int p,int v,int u) { vis[p]=1; dis[p]=v;pd[p]=u; int len=gra[p].size(); for(int i=0;i<len;i++) { int e=gra[p][i].ed,vv=gra[p][i].v,id=gra[p][i].id; if(flag[id]||flag[id^1]||vis[e])continue; if(vv>v) dfs(e,vv,id); else dfs(e,v,u); } } int main() { //freopen("/home/axorb/in","r",stdin); while(scanf("%d",&m)==1) { hash.clear(); hash["Park"]=0;n=0; eid=0;head[n++]=-1; for(int i=0;i<m;i++) { string s1,s2;int v; cin>>s1>>s2>>v; if(!hash.count(s1))hash[s1]=n,head[n++]=-1; if(!hash.count(s2))hash[s2]=n,head[n++]=-1; int id1=hash[s1],id2=hash[s2]; addedge(id1,id2,v); addedge(id2,id1,v); } cin>>k; for(int i=0;i<n;i++) { dis[i]=inf; vis[i]=0; gra[i].clear(); } int ans=0; for(int i=1;i<n;i++)//构建最小生成树森林 if(dis[i]==inf) { int minn=inf,pos=-1,gk=-1; while(!que.empty())que.pop(); dis[i]=0;que.push(Node(i,0)); while(!que.empty()) { int s=que.top().ed; que.pop(); if(vis[s])continue; vis[s]=1; ans+=dis[s]; if(s!=i) { gra[pd[s]].push_back(Node(s,pv[s],pg[s])); gra[s].push_back(Node(pd[s],pv[s],pg[s])); } for(int j=head[s];~j;j=nxt[j]) { int e=ed[j],v=val[j]; if(e==0) { if(minn>v) { minn=v; pos=s; gk=j; } continue; } if(!vis[e]&&dis[e]>v) { dis[e]=v;pd[e]=s; pv[e]=v;pg[e]=j; que.push(Node(e,v)); } } } //这棵最小生成树选择一条与V0相关联的最小边,并更新其他点 ans+=minn;k--;flag[gk]=flag[gk^1]=1; for(int i=0;i<n;i++)vis[i]=0; dfs(pos,-1,-1); } //这里,如果k<0,则说明不存在度限制最小生成树 while(k>0)//进行最小差值运算 { k--; int minn=inf,pos,gk; for(int i=head[0];~i;i=nxt[i]) { int e=ed[i],v=val[i]; if(flag[i]||flag[i^1]||dis[e]==-1)continue; int k=v-dis[e]; if(k<minn) { minn=k; pos=e; gk=i; } } if(minn>=0)break; ans+=minn; flag[gk]=flag[gk^1]=1; int g=pd[pos]; flag[g]=flag[g^1]=1; dfs(pos,-1,-1); } printf("Total miles driven: %d\n",ans); } return 0; }