宝藏
本来是刷状压dp的,然而不会。。
首先,打了一个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\n",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(); } }; 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\n",ans); return 0; }
不断改种子,提交17次,O2优化,终于卡了过去(%Ha
(状压dp什么的。。61吧。。