宝藏
首先,打了一个prim,得了45分
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<queue> 5 using namespace std; 6 #define N 15 7 #define M 2000 8 #define INF 0x3f3f3f3f 9 int n,m,dis[N],dep[N],ans; 10 int Head[N],tot; 11 bool vis[N]; 12 struct NODE{ 13 int to,w,next; 14 } e[M]; 15 struct cmp{ 16 bool operator()(int a,int b){ 17 return dis[a]>dis[b]; 18 } 19 }; 20 priority_queue< int , vector<int> , cmp > q; 21 inline int read(){ 22 int x=0; char c=getchar(); 23 while(c<'0'||c>'9') c=getchar(); 24 while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); } 25 return x; 26 } 27 inline void add(int x,int y,int w){ 28 e[++tot].to=y; 29 e[tot].w=w; 30 e[tot].next=Head[x]; 31 Head[x]=tot; 32 } 33 int prim(int St){ 34 int sum=0; 35 for(int i=1;i<=n;i++){ 36 dis[i]=1000000; 37 dep[i]=14; vis[i]=0; 38 } 39 dis[St]=dep[St]=0; 40 q.push(St); 41 while(!q.empty()){ 42 int u=q.top(); q.pop(); 43 if(vis[u]) continue; 44 vis[u]=1; sum+=dis[u]; 45 for(int i=Head[u];i;i=e[i].next){ 46 int v=e[i].to; 47 if(dis[v]>(dep[u]+1)*e[i].w){ 48 dep[v]=dep[u]+1; 49 dis[v]=dep[v]*e[i].w; 50 } 51 q.push(v); 52 } 53 } 54 return sum; 55 } 56 int main() 57 { 58 scanf("%d%d",&n,&m); 59 int x,y,w; 60 for(int i=1;i<=m;i++){ 61 x=read(); y=read(); w=read(); 62 add(x,y,w); add(y,x,w); 63 } 64 ans=INF; 65 for(int i=1;i<=n;i++) 66 ans=min(ans,prim(i)); 67 printf("%d ",ans); 68 return 0; 69 }
然后看到题解里状压DP、模拟退火什么玩意的。。
模拟退火我是不会的
不过随机化什么的好像可以骗一下分
于是将代码改了一点
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<queue> using namespace std; #define N 15 #define M 2000 #define INF 0x3f3f3f3f int n,m,dis[N],dep[N],ans; int Head[N],tot; bool vis[N]; struct NODE{ int to,w,next; } e[M]; struct cmp{ bool operator()(int a,int b){ return dis[a]+rand()>dis[b]+rand(); //非常low的随机化 } }; priority_queue< int , vector<int> , cmp > q; inline int read(){ int x=0; char c=getchar(); while(c<'0'||c>'9') c=getchar(); while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); } return x; } inline void add(int x,int y,int w){ e[++tot].to=y; e[tot].w=w; e[tot].next=Head[x]; Head[x]=tot; } int prim(int St){ int sum=0; for(int i=1;i<=n;i++){ dis[i]=1000000; dep[i]=14; vis[i]=0; } dis[St]=dep[St]=0; q.push(St); while(!q.empty()){ int u=q.top(); q.pop(); if(vis[u]) continue; vis[u]=1; sum+=dis[u]; for(int i=Head[u];i;i=e[i].next){ int v=e[i].to; if(vis[v]) continue; if(dis[v]>(dep[u]+1)*e[i].w){ dep[v]=dep[u]+1; dis[v]=dep[v]*e[i].w; } q.push(v); } } return sum; } int main() { srand(19260817); scanf("%d%d",&n,&m); int x,y,w; for(int i=1;i<=m;i++){ x=read(); y=read(); w=read(); add(x,y,w); add(y,x,w); } ans=INF; int g=200; while(g--){ srand(rand()); for(int i=1;i<=n;i++) ans=min(ans,prim(i)); } printf("%d ",ans); return 0; }
很迷的是上面代码的复杂度巨大
然后发现一个很严重的问题
邻接表就跟吔了shi一样
我们将邻接表改成邻接矩阵,
又改了一下随机化的方式
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<queue> using namespace std; const int MAXN=15,MAXM=2010; const int INF=0x3f3f3f3f; int n,m,g[MAXN][MAXN]; int Head[MAXN],num; struct NODE{ int pos,cost; }; struct cmp{ bool operator ()(NODE a,NODE b){ return a.cost>b.cost; } }; priority_queue< NODE,vector<NODE>,cmp > que; bool vis[MAXN]; NODE s[MAXM]; int cnt,dis[MAXN],tot[MAXN]; int prim(int S){ int ans=0; memset(vis,0,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); que.push(NODE{S,0});dis[S]=tot[S]=0; for(int i=1;i<=n;i++){ cnt=0; while(!que.empty()&&(vis[que.top().pos]||rand()%(i+1)<1)){ if(!vis[que.top().pos]) s[++cnt]=que.top(); que.pop(); } int k; if(que.empty()) k=s[cnt].pos,cnt--; else k=que.top().pos,que.pop(); vis[k]=1; ans+=dis[k]; if(ans>INF) return INF; for(int i=1;i<cnt;i++) que.push(s[i]); for(int i=1;i<=n;i++) if(g[k][i]<INF){ if(dis[i]>(tot[k]+1)*g[k][i]){ tot[i]=tot[k]+1; dis[i]=tot[i]*g[k][i]; } que.push(NODE{i,dis[i]}); } } return ans; } int main() { memset(g,0x3f,sizeof(g)); scanf("%d%d",&n,&m); int x,y,w; for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&w); if(w<g[x][y]) g[x][y]=g[y][x]=w; } int ans=INF; int t=500; while(t--) for(int i=1;i<=n;i++) ans=min(ans,prim(i)); printf("%d ",ans); return 0; }
以上做法都不大靠谱,大家还是状压DP吧(逃