标签:tor 决定 reg this erb rip width contain elves
Time Limit: 5000MS | Memory Limit: 10000K | |
Total Submissions:11615 | Accepted: 4172 |
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
思路
一开始在网上搜索题解,照着他们的算法写,写完了才发现,他们有最重要的一步没有讲,幸好此时峰巨告诉了我算法的全过程,orz orz orz。
算法:
1.无视Park及其它的边,建立最小生成树(森林)。
2.选择park到每个树的最短边,与树相连。
3.此时,park到每棵树还剩了一些边,枚举他们,每一条边加进去都会有一个环,删去环内的最大边。枚举的时候不要真实操作(或者操作后还原),而是记录他们的值,选择最大的,再进行删边操作。
4.重复第三步(k-第一步最小生成树的数目)次
博主水平不高,如需帮助,请在下方留言
1 #include<iostream> 2 #include<vector> 3 #include<cstring> 4 #include<algorithm> 5 #include<cstdio> 6 using namespace std; 7 const int inf = 2100000000; 8 int mp[22][22],pp; 9 int dis[22],disx[22],n,k,kk; 10 int book[22],flag[22][22]; 11 char name[22][515]; 12 int e1,e2,f[22]; 13 bool vis[22]; 14 int fo[22]; 15 struct node 16 { 17 int pio; 18 int wei; 19 int ex1,ex2; 20 }getr[22],exa; 21 22 23 int prim(int k) 24 { 25 dis[k]=0; 26 int ans=0; 27 28 while(true){ 29 int t=0; 30 for(int i=1;i<=n;i++){ 31 if(!book[i]&&dis[i]<dis[t]){ 32 t=i; 33 } 34 } 35 if(t==0){break;} 36 ans+=dis[t];book[t]=k;flag[disx[t]][t]=flag[t][disx[t]]=true; 37 for(int i=1;i<=n;i++){ 38 if(!book[i]&&dis[i]>mp[t][i]){ 39 dis[i]=mp[t][i]; 40 disx[i]=t; 41 } 42 } 43 44 } 45 return ans; 46 } 47 48 void init() 49 { 50 for(int i=1;i<=22;i++){ 51 for(int j=1;j<=22;j++){ 52 mp[i][j]=inf; 53 } 54 } 55 for(int i=0;i<=22;i++){ 56 dis[i]=inf; 57 } 58 } 59 60 void scan() 61 { 62 int s,x,y; 63 scanf("%d",&n); 64 char a[15],b[15]; 65 int t=0; 66 init(); 67 for(int i=1;i<=n;i++){ 68 scanf("%s%s%d",a,b,&s); 69 x=y=-1; 70 for(int j=1;j<=t;j++){ 71 if(!strcmp(name[j],a)){x=j;} 72 if(!strcmp(name[j],b)){y=j;} 73 } 74 if(x==-1){x=++t;strcpy(name[t],a);} 75 if(y==-1){y=++t;strcpy(name[t],b);} 76 mp[x][y]=mp[y][x]=s; 77 } 78 79 80 scanf("%d",&k); 81 n=t; 82 } 83 84 int dfs(int p)//找出环内最大边 85 { 86 vis[p]=true; 87 int ans=-1,op; 88 89 for(int i=1;i<=n;i++){ 90 if(flag[i][p]&&i==pp&&f[p]!=i){e1=i;e2=p;return mp[i][p];} 91 if(!vis[i]&&flag[i][p]){ 92 f[i]=p; 93 op=dfs(i); 94 95 if(op!=-1){ 96 if(op<mp[i][p]){e1=i;e2=p;return mp[i][p];} 97 else return op; 98 } 99 } 100 } 101 return ans; 102 } 103 104 int solve(int p) 105 { 106 107 int tx=0,ans=0;pp=p; 108 for(int i=1;i<=kk;i++){ 109 tx=0; 110 memset(getr,0,sizeof(getr)); 111 // cout<<endl; 112 // cout<<"第"<<i<<"次轮回"<<endl; 113 for(int j=1;j<=n;j++){ 114 if(flag[p][j]||mp[p][j]==inf){continue;} 115 memset(vis,0,sizeof(vis)); 116 flag[p][j]=flag[j][p]=true; 117 // cout<<"新增的边 "<<j<<"--"<<p<<endl; 118 int yj=dfs(p); 119 // cout<<"删除边的长度 "<<yj<<endl; 120 getr[tx].pio=j;getr[tx].wei=mp[p][j]-yj; 121 getr[tx].ex1=e1;getr[tx].ex2=e2; 122 tx++; 123 flag[p][j]=flag[j][p]=false;//还原 124 } 125 exa.pio=0;exa.wei=inf; 126 for(int i=0;i<n;i++){ 127 if(exa.wei>getr[i].wei){exa=getr[i];} 128 } 129 // cout<<"最终的决定 "<<exa.ex1<<" "<<exa.ex2<<" "<<exa.pio<<" "<<exa.wei<<endl; 130 ans+=min(exa.wei,0); 131 flag[p][exa.pio]=flag[exa.pio][p]=true; 132 flag[exa.ex1][exa.ex2]=flag[exa.ex2][exa.ex1]=false; 133 } 134 return ans; 135 } 136 137 138 int main() 139 { 140 scan(); 141 int p; 142 for(int i=1;i<=n;i++){ 143 if(!strcmp(name[i],"Park")){p=i;break;} 144 } 145 int m=0,ans=0; 146 book[p]=p; 147 for(int i=1;i<=n;i++){ 148 if(!book[i]){ 149 m++; 150 ans+=prim(i); 151 } 152 } 153 // cout<<"初次最小生成树 "<<ans<<endl; 154 kk=k; 155 for(int i=1;i<=m;i++){ 156 int minn=inf,ss=-1;; 157 for(int j=1;j<=n;j++){ 158 if(!flag[p][j]&&!vis[book[j]]&&mp[p][j]!=inf){ 159 if(mp[j][p]<minn){minn=mp[j][p];ss=j;} 160 } 161 } 162 if(minn!=inf){ 163 kk--; 164 ans+=mp[p][ss];vis[book[ss]]=true; 165 flag[p][ss]=flag[ss][p]=true; 166 } 167 } 168 // cout<<"最小m度生成树 "<<ans<<endl; 169 printf("Total miles driven: %d\n",ans+solve(p)); 170 }
POJ 1639 Picnic Planning 最小k度生成树
标签:tor 决定 reg this erb rip width contain elves
原文地址:https://www.cnblogs.com/ZGQblogs/p/9388924.html