• [cf1149D]Abandoning Roads


    根据kruskal的贪心过程,先将所有$a$类边连起来,对于一个连通块内的两点,必然通过$a$边联通

    考虑对于一条最短路径,必然是一段(可能为空)$a$类边+1条$b$类边,同时其合法当且仅当这些$b$类边都能被加入最小生成树中,即不会与$a$类边产生环,又即不重复经过一个连通块

    状压之前经过的连通块求最短路(当使用$b$类边离开后再加入),那么时间复杂度为$o(2^{n}m)$

    注意到我们是在求最短路径,若一个连通块点数小于4,则必然从连通块内部走,因此复杂度变为$o(2^{frac{n}{4}}m)$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 105
     4 struct ji{
     5     int nex,to,len;
     6 }edge[N<<2];
     7 queue<pair<int,int> >q;
     8 int E,n,m,a,b,x,y,z,head[N],f[N],sz[N],bl[N],vis[N][200005],d[N][200005];
     9 int find(int k){
    10     if (k==f[k])return k;
    11     return f[k]=find(f[k]);
    12 }
    13 void merge(int x,int y){
    14     x=find(x),y=find(y);
    15     if (x!=y){
    16         f[x]=y;
    17         sz[y]+=sz[x];
    18     }
    19 }
    20 void add(int x,int y,int z){
    21     edge[E].nex=head[x];
    22     edge[E].to=y;
    23     edge[E].len=z;
    24     head[x]=E++;
    25 }
    26 void spfa(){
    27     memset(d,0x3f,sizeof(d));
    28     d[1][0]=0;
    29     vis[1][0]=1;
    30     q.push(make_pair(1,0));
    31     while (!q.empty()){
    32         int k=q.front().first,s=q.front().second;
    33         q.pop();
    34         for(int i=head[k];i!=-1;i=edge[i].nex){
    35             int v=edge[i].to,ss=s;
    36             if (edge[i].len==b){
    37                 if (find(edge[i].to)==find(k))continue;
    38                 ss|=bl[k];
    39             }
    40             if (((ss&bl[v])==0)&&(d[v][ss]>d[k][s]+edge[i].len)){
    41                 d[v][ss]=d[k][s]+edge[i].len;
    42                 if (!vis[v][ss]){
    43                     vis[v][ss]=1;
    44                     q.push(make_pair(v,ss));
    45                 }
    46             }
    47         }
    48         vis[k][s]=0;
    49     }
    50 }
    51 int main(){
    52     scanf("%d%d%d%d",&n,&m,&a,&b);
    53     memset(head,-1,sizeof(head));
    54     for(int i=1;i<=n;i++){
    55         f[i]=i;
    56         sz[i]=1;
    57     }
    58     for(int i=1;i<=m;i++){
    59         scanf("%d%d%d",&x,&y,&z);
    60         if (z==a)merge(x,y);
    61         add(x,y,z);
    62         add(y,x,z);
    63     }
    64     m=0;
    65     for(int i=1;i<=n;i++)
    66         if ((f[i]==i)&&(sz[i]>=4))bl[i]=(1<<m++);
    67     for(int i=1;i<=n;i++)bl[i]=bl[find(i)];
    68     spfa();
    69     for(int i=1;i<=n;i++){
    70         int ans=0x3f3f3f3f;
    71         for(int j=0;j<(1<<m);j++)ans=min(ans,d[i][j]);
    72         printf("%d ",ans);
    73     }
    74 }
    View Code
  • 相关阅读:
    微信小程序与Html交互
    vue plupload 的使用
    mac 使用远程连接
    ajax 设置Access-Control-Allow-Origin实现跨域访问
    javascript取模运算是怎么算的?其实是取余数
    [G]Java获取泛型T的类型 T.class
    [G]java反射获得泛型参数getGenericSuperclass()
    Java中的Type类型详解
    利用ParameterizedType获取泛型参数类型
    Type类型详解
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13877982.html
Copyright © 2020-2023  润新知