• 【TYVJ 五月图论专项有奖比赛】


    最短路+TSP+最小生成树+倍增LCA+TreeDP


    第一题

      其实是个TSP问题(然而我没发现),但是关键点很少,只有5个,所以用dij+heap分别预处理出来这五个点为源的最短路……

      然后枚举起点 i ,枚举这5个点的经过顺序,然后O(1)处理答案就可以了……

      容易写错的地方是 五个点的标号(a[i]),以及第几个点(i),这个地方容易搞混……

      我爆零的地方是:有个地方原来写的是 i 循环,然而我修改了以后内层变成 j 循环了,但是我没改循环内的语句……

      还有就是数组应该开 len[M<<1]的,我开成len[N<<1] 了。

     1 #include<queue>
     2 #include<vector>
     3 #include<cstdio>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<iostream>
     7 #include<algorithm>
     8 #define rep(i,n) for(int i=0;i<n;++i)
     9 #define F(i,j,n) for(int i=j;i<=n;++i)
    10 #define D(i,j,n) for(int i=j;i>=n;--i)
    11 using namespace std;
    12 
    13 int getint(){
    14     int v=0,sign=1; char ch=getchar();
    15     while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();}
    16     while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();}
    17     return v*sign;
    18 }
    19 typedef long long LL;
    20 const int N=10010,M=50010,INF=~0u>>2;
    21 /*******************template********************/
    22 int to[M<<1],next[M<<1],len[M<<1],head[N],cnt;
    23 void add(int x,int y,int z){
    24     to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt; len[cnt]=z;
    25     to[++cnt]=x; next[cnt]=head[y]; head[y]=cnt; len[cnt]=z;
    26 }
    27 
    28 int n,m,k;
    29 int a[10],b[10],d[10][N];
    30 bool vis[N],sign[N];
    31 struct node{int x,d;};
    32 bool operator < (node a,node b){return a.d>b.d;}
    33 priority_queue<node>Q;
    34 
    35 void dij(int s){
    36     memset(d[s],0x3f,sizeof d[s]);
    37     memset(vis,0,sizeof vis);
    38     d[s][a[s]]=0;
    39     Q.push((node){a[s],0});
    40     while(!Q.empty()){
    41         int x=Q.top().x; Q.pop();
    42         if (vis[x]) continue;
    43         vis[x]=1;
    44         for(int i=head[x];i;i=next[i])
    45             if (d[s][to[i]]>d[s][x]+len[i]){
    46                 d[s][to[i]]=d[s][x]+len[i];
    47                 Q.push((node){to[i],d[s][to[i]]});
    48             }
    49     }
    50 }
    51 int ans=1e9+10;
    52 void check(){
    53     int tmp=0;
    54     F(i,1,n){
    55         tmp=0;
    56         if (!sign[i]){
    57             tmp+=d[b[1]][i]+d[b[k]][i];
    58             F(j,1,k-1) tmp+=d[b[j]][ a[b[j+1]] ];
    59             ans=min(ans,tmp);
    60         }
    61     }
    62 }
    63 bool chk[10];
    64 void dfs(int x){
    65     if (x==k+1) check();
    66     F(i,1,k) if (!chk[i]){
    67         b[x]=i;
    68         chk[i]=1;
    69         dfs(x+1);
    70         b[x]=0;
    71         chk[i]=0;
    72     }
    73 }
    74 int main(){
    75     n=getint(); m=getint(); k=getint();
    76     F(i,1,k){
    77         a[i]=getint();
    78         sign[a[i]]=1;
    79     }
    80     F(i,1,m){
    81         int x=getint(),y=getint(),z=getint();
    82         add(x,y,z);
    83     }
    84     F(i,1,k) dij(i);
    85     dfs(1);
    86     printf("%d
    ",ans);
    87     return 0;
    88 }
    View Code

    第二题

      跟NOIP 2012的d1t3(希望没记错时间……那题叫货车运输……)几乎完全相同的题,只不过那题是找最小,这题是最大。

      搞一个最大生成树,然后在树上倍增就可以了。

      40分?……因为忘记判impossible了……2333

     1 #include<vector>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<iostream>
     6 #include<algorithm>
     7 #define rep(i,n) for(int i=0;i<n;++i)
     8 #define F(i,j,n) for(int i=j;i<=n;++i)
     9 #define D(i,j,n) for(int i=j;i>=n;--i)
    10 using namespace std;
    11 typedef long long LL;
    12 inline int getint(){
    13     int r=1,v=0; char ch=getchar();
    14     for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1;
    15     for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch;
    16     return r*v;
    17 }
    18 const int N=1e5+10,M=3e5+10;
    19 /*******************template********************/
    20 
    21 int to[N<<1],next[N<<1],head[N],len[N<<1],cnt;
    22 void add(int x,int y,int z){
    23     to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt; len[cnt]=z;
    24     to[++cnt]=x; next[cnt]=head[y]; head[y]=cnt; len[cnt]=z;
    25 }
    26 struct edge{int u,v,w;}E[M];
    27 bool cmp(const edge &a,const edge &b){return a.w<b.w;}
    28 int f[N],sz[N];
    29 inline int getf(int x){return f[x]==x ? x : getf(f[x]);}
    30 
    31 int fa[N][20],mx[N][20],dep[N],n,m;
    32 void dfs(int x){
    33     F(i,1,17)
    34         if (dep[x]>=(1<<i)){
    35             fa[x][i]=fa[fa[x][i-1]][i-1];
    36             mx[x][i]=max(mx[fa[x][i-1]][i-1],mx[x][i-1]);
    37         }else break;
    38     for(int i=head[x];i;i=next[i])
    39         if (to[i]!=fa[x][0]){
    40             fa[to[i]][0]=x;
    41             dep[to[i]]=dep[x]+1;
    42             mx[to[i]][0]=len[i];
    43             dfs(to[i]);
    44         }
    45 }
    46 int query(int x,int y){
    47     if (dep[x]<dep[y]) swap(x,y);
    48     int t=dep[x]-dep[y];
    49     int ans=0;
    50     F(i,0,17) if (t&(1<<i)){
    51         ans=max(mx[x][i],ans);
    52         x=fa[x][i];
    53     }
    54     D(i,17,0) if (fa[x][i]!=fa[y][i]){
    55         ans=max(mx[x][i],ans);
    56         ans=max(mx[y][i],ans);
    57         x=fa[x][i]; y=fa[y][i];
    58     }
    59     if (x!=y) ans=max(ans,max(mx[x][0],mx[y][0]));
    60     return ans;
    61 }
    62 int main(){
    63     n=getint(); m=getint();
    64     F(i,1,m){
    65         int x=getint(),y=getint(),z=getint();
    66         E[i]=(edge){x,y,z};
    67     }
    68     sort(E+1,E+m+1,cmp);
    69     F(i,1,n) f[i]=i,sz[i]=1;
    70     F(i,1,m){
    71         int f1=getf(E[i].u),f2=getf(E[i].v);
    72         if (f1!=f2){
    73             if (sz[f1]>sz[f2]) swap(f1,f2);
    74             f[f1]=f2;
    75             sz[f2]+=sz[f1];
    76             add(E[i].u,E[i].v,E[i].w);
    77         }
    78     }
    79     
    80     dfs(1);
    81     int T=getint();
    82     while(T--){
    83         int x=getint(),y=getint();
    84         if (getf(x)!=getf(y)) puts("impossible");
    85         else printf("%d
    ",query(x,y));
    86     }
    87     return 0;
    88 }
    View Code

    第三题

      我并不会写……只好预处理出来dist[i][j]数组,然后$N^2$枚举+O(n)判断……三次方的做法骗了30分= =

      然而正解是找树的重心?预处理出来每棵子树的答案,由于整棵树分成的两部分是一棵完整的子树+剩下的部分,所以枚举那个砍掉的子树?在再加上一些神奇的技巧……

      然而一上午也没yy出来果然代码能力就是渣渣,sad……

      UPD:2015年5月20日 16:28:33

      Orz zyf神犇

      果然是……枚举断了哪条边,然后暴力修改= =用dfs整棵树来选边就可以,从当前点沿fa修改上去,两半树各求一遍答案……ok……无限ym啊……

     1 //TYVJ C
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<iostream>
     6 #include<algorithm>
     7 #define rep(i,n) for(int i=0;i<n;++i)
     8 #define F(i,j,n) for(int i=j;i<=n;++i)
     9 #define D(i,j,n) for(int i=j;i>=n;--i)
    10 #define pb push_back
    11 using namespace std;
    12 typedef long long LL;
    13 inline int getint(){
    14     int r=1,v=0; char ch=getchar();
    15     for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1;
    16     for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch;
    17     return r*v;
    18 }
    19 const int N=100010;
    20 /*******************template********************/
    21 int to[N<<1],next[N<<1],head[N],cnt;
    22 void add(int x,int y){
    23     to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt;
    24     to[++cnt]=x; next[cnt]=head[y]; head[y]=cnt;
    25 }
    26 
    27 int n,a[N],f[N][2],dep[N],s[N],fa[N],cut;
    28 LL g[N],ans=1e15;
    29 void dfs(int x){
    30     for(int i=head[x];i;i=next[i])
    31         if (to[i]!=fa[x]){
    32             dep[to[i]]=dep[x]+1;
    33             fa[to[i]]=x;
    34             dfs(to[i]);
    35             s[x]+=s[to[i]];
    36             if (s[to[i]]>s[f[x][0]]) f[x][1]=f[x][0],f[x][0]=to[i];
    37             else if (s[to[i]]>s[f[x][1]]) f[x][1]=to[i];
    38             g[x]+=g[to[i]]+s[to[i]];
    39         }
    40 }
    41 LL getans(int x,int cnt){
    42     int t=(f[x][0]==cut || s[f[x][1]]>s[f[x][0]]) ? f[x][1] : f[x][0];
    43     if (2*s[t]>cnt) return 2*s[t]-cnt+getans(t,cnt);
    44     else return 0;
    45 }
    46 void dp(int x){
    47     for(int i=head[x];i;i=next[i])
    48         if (to[i]!=fa[x]){
    49             cut=to[i];
    50             for(int j=x;j;j=fa[j]) s[j]-=s[to[i]];
    51             ans=min(ans,g[1]-g[to[i]]-(LL)s[to[i]]*dep[to[i]]-getans(1,s[1])+g[to[i]]-getans(to[i],s[to[i]]));
    52             for(int j=x;j;j=fa[j]) s[j]+=s[to[i]];
    53             dp(to[i]);
    54         }
    55 }
    56 
    57 int main(){
    58 #ifndef ONLINE_JUDGE
    59     freopen("C.in","r",stdin);
    60     freopen("C.out","w",stdout);
    61 #endif
    62     n=getint();
    63     F(i,2,n){
    64         int x=getint(),y=getint();
    65         add(x,y);
    66     }
    67     F(i,1,n) s[i]=getint();
    68     dfs(1);
    69     dp(1);
    70     printf("%lld
    ",ans);
    71     return 0;
    72 }
    View Code
  • 相关阅读:
    asp.net Core 中AuthorizationHandler 实现自定义授权
    Android 动态获取ListView的高度
    artDialog是一个基于javascript编写的对话框组件,它拥有精致的界面与友好的接口
    Java日期时间思维导图整理
    《领域驱动设计》第二部分:模型驱动设计的构造块 第四章:分离领域 阅读笔记
    《领域驱动设计》第一部分:让领域模型发挥作用 第三章:绑定模型和实现 阅读笔记
    《领域驱动设计》干货整理
    简单的服务熔断方案
    框架设计注意事项——生命周期
    【翻译】 Guice 动机——依赖注入的动机
  • 原文地址:https://www.cnblogs.com/Tunix/p/4511404.html
Copyright © 2020-2023  润新知