POJ 1639 最小度限制生成樹(TLE,原因:未知)
阿新 • • 發佈:2018-12-21
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include<algorithm> #include <set> #include <queue> #include <stack> #include<vector> #include<map> #include<ctime> #define ll long long using namespace std; const int N=36; int v[N];//聯通塊標號 int ver[N];//鄰接表邊N的終點 int edge[N*N+100];//鄰接表邊N的權值 int head[N];//鄰接表點N的最後一條邊 int next[N];//鄰接表邊N的下一條邊 int tot;//鄰接表 中邊數 int cnt;//聯通塊的數目 int ff1[N]; int ff2[N]; int ff3[N]; void add(int x,int y,int z)//鄰接表加邊 { ver[++tot]=y; edge[tot]=z; next[tot]=head[x]; head[x]=tot; } void dfs(int x)//得到x所在的聯通塊 { v[x]=cnt; for(int i=head[x];i;i=next[i]) { int y=ver[i]; if(v[y])continue; dfs(y); } } int dis[N][N]; map<string,int>mm; int num; int d[N];//prime中以點N為終點的那條邊; bool flag[N]; int prime(int index,int pos,int nn)//聯通塊標號、起點 { for(int i=0;i<=32;++i)d[i]=999999999; memset(flag,0,sizeof(flag)); d[pos]=0; for(int i=1;i<nn;++i) { int x=0; for(int j=1;j<=num;++j) if(!flag[j]&&((x==0)||d[j]<d[x])&&v[j]==index)x=j; flag[x]=1; for(int j=head[x];j;j=next[j]) { int y=ver[j]; if(!flag[y]&&v[y]==index) { if(edge[j]<d[y]) { d[y]=edge[j]; ff2[y]=x; } d[y]=min(d[y],edge[j]); } } } int ans=0; for(int i=1;i<=num;++i) { if(v[i]==index)ans+=d[i]; } return ans; } int dfs2(int xx)//找1->xx的最長邊 { int ans=0; for(int i=xx;i!=ff1[v[xx]];i=ff2[i]) { ans=max(ans,dis[i][ff2[i]]); } return ans; } int main() { int n; while(cin>>n) { memset(dis,0,sizeof(dis)); tot=cnt=0; mm.clear(); memset(v,0,sizeof(v)); memset(ver,0,sizeof(ver)); memset(head,0,sizeof(head)); memset(next,0,sizeof(next)); memset(edge,0,sizeof(edge)); string str,t; int x; mm.insert(make_pair("Park",1 )); num++; for(int i=1;i<=n;++i) { cin>>str>>t>>x; int d1,d2; if(mm.find(str)==mm.end()) { num++; mm.insert(make_pair(str,num)); d1=num; } else { d1=mm.find(str)->second; } if(mm.find(t)==mm.end()) { num++; mm.insert(make_pair(t,num)); d2=num; } else { d2=mm.find(t)->second; } dis[d1][d2]=dis[d2][d1]=x; add(d1,d2,x); add(d2,d1,x); } int s; cin>>s; for(int i=2;i<=num;++i) { if(v[i])continue; cnt++; dfs(i); } //cout<<cnt<<".."<<endl; int ans=0; for(int i=1;i<=cnt;++i) { int minn=999999999; int pos; int nn; for(int j=1;j<=num;++j) { int nn=0; if(v[j]==i) { nn++; if(dis[j][1]<minn)minn=dis[j][1],pos=j; } } if(minn!=999999999)ans+=minn; ans+=prime(i,pos,nn); ff1[i]=pos; } //cout<<ff1[cnt]<<endl; int kk=cnt; for(int j=head[1];j;j=next[j]) { int xx=ver[j];//邊的終點 int vv=dfs2(xx); if(edge[j]<vv) { //cout<<edge[j]<<" "<<vv<<endl; ans=ans+edge[j]-vv; kk++; if(kk==s)break; } } cout<<"Total miles driven: "<<ans<<endl; } }
//提交時稍作修改,scanf...... #include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include<algorithm> #include <set> #include <queue> #include <stack> #include<vector> #include<map> #include<ctime> #define ll long long using namespace std; const int N=36; const int M=36*36; int v[N];//聯通塊標號 int ver[M];//鄰接表邊M的終點 int edge[N*N];//鄰接表邊M的權值 int head[N];//鄰接表點N的最後一條邊 int next[M];//鄰接表邊M的下一條邊 int tot;//鄰接表 中邊數 int cnt;//聯通塊的數目 int ff1[N]; int ff2[N]; int ff3[N]; void add(int x,int y,int z)//鄰接表加邊 { ver[++tot]=y; edge[tot]=z; next[tot]=head[x]; head[x]=tot; } void dfs(int x)//得到x所在的聯通塊 { v[x]=cnt; for(int i=head[x];i!=-1;i=next[i]) { int y=ver[i]; if(v[y])continue; dfs(y); } } int dis[N][N]; map<string,int>mm; int num; int d[N];//prime中以點N為終點的那條邊; bool flag[N]; int prime(int index,int pos,int nn)//聯通塊標號、起點 { memset(d,0x3f,sizeof(d)); memset(flag,0,sizeof(flag)); d[pos]=0; for(int i=1;i<nn;++i) { int x=0; for(int j=1;j<=num;++j) if(!flag[j]&&((x==0)||(d[j]<d[x]))&&v[j]==index)x=j; flag[x]=1; for(int j=head[x];j!=-1;j=next[j]) { int y=ver[j]; if(!flag[y]&&v[y]==index) { if(edge[j]<d[y]) { d[y]=edge[j]; ff2[y]=x; } d[y]=min(d[y],edge[j]); } } } int ans=0; for(int i=1;i<=num;++i) { if(v[i]==index)ans+=d[i]; } return ans; } int dfs2(int xx)//找1->xx的最長邊 { int ans=0; for(int i=xx;i!=ff1[v[xx]];i=ff2[i]) { ans=max(ans,dis[i][ff2[i]]); } return ans; } char ch1[110]; char ch2[110]; int main() { int n; while(scanf("%d",&n)!=EOF) { memset(dis,0,sizeof(dis)); tot=cnt=0; mm.clear(); memset(v,0,sizeof(v)); memset(ver,0,sizeof(ver)); memset(head,0,sizeof(head)); memset(next,-1,sizeof(next)); memset(edge,0,sizeof(edge)); string str,t; int x; mm.insert(make_pair("Park",1 )); num++; getchar(); for(int i=1;i<=n;++i) { scanf("%s",ch1); getchar(); scanf("%s",ch2); getchar(); scanf("%d",&x); str=ch1; t=ch2; //cin>>str>>t>>x; int d1,d2; if(mm.find(str)==mm.end()) { num++; mm.insert(make_pair(str,num)); d1=num; } else { d1=mm.find(str)->second; } if(mm.find(t)==mm.end()) { num++; mm.insert(make_pair(t,num)); d2=num; } else { d2=mm.find(t)->second; } dis[d1][d2]=dis[d2][d1]=x; add(d1,d2,x); add(d2,d1,x); } int s; scanf("%d",&s); for(int i=2;i<=num;++i) { if(v[i])continue; cnt++; dfs(i); } //cout<<cnt<<".."<<endl; int ans=0; for(int i=1;i<=cnt;++i) { int minn=0X3F; int pos; int nn; for(int j=1;j<=num;++j) { int nn=0; if(v[j]==i) { nn++; if(dis[j][1]<minn)minn=dis[j][1],pos=j; } } if(minn!=999999999)ans+=minn; ans+=prime(i,pos,nn); ff1[i]=pos; } //cout<<ff1[cnt]<<endl; int kk=cnt; for(int j=head[1];j!=-1;j=next[j]) { int xx=ver[j];//邊的終點 int vv=dfs2(xx); if(edge[j]<vv) { //cout<<edge[j]<<" "<<vv<<endl; ans=ans+edge[j]-vv; kk++; if(kk==s)break; } } printf("Total miles driven: %d\n",ans); //cout<<""<<ans<<endl; } return 0; }