zoukankan      html  css  js  c++  java
  • HZOI2019 B. 那一天她离我而去 最小环

    题目大意:https://www.cnblogs.com/Juve/articles/11219089.html

    那一天,我们......行啦,不要帮出题人脑补画面了,我们来正经的题解

    我们发现我们可以把与1号节点相连的所有节点取出,如果我们把最小环在1号节点处断开,那么最小环断成的链一定是以这些节点中的某一个节点作为起点,另一个节点作为终点的一条路路径。
    如果不考虑时间复杂度,我们完全可以枚举作为起点的节点,每次都跑一遍最短路来更新答案。
    但是上面的做法肯定会爆炸,所以我们考虑如何降低复杂度。

    我们考虑把所有的节点分为两组,一组中的所有点作为起点,另一组中的所有点作为终点,一起跑最短路,更新答案。
    如此我们发现只要我们能够保证真正贡献答案的一对节点会在某一次分组当中被分到不同组,我们就可以保证算法的正确性。
    因为起点与终点的编号肯定不相同,于是我们可以按照二进制分组,枚举每个二进制位,按照当前二进制位的0/1情况来进行分组。

    我看好像没有人用这种方法的,其实dij就可以过,用dij求1号节点开始的最小环

    别告诉我你不会求最小环。

    我们枚举1号点连接的每一条边,设起点为fr[i],终点为to[i],

    先把这条边权变成0x3f3f3f3f,跑dij,求出此时fr[i]到to[i]的最短路,再加上原来这条边的权值就是一个环的大小,

    更新答案:ans=min(dis[to[i]]+w[i]);

    就是把fr[i]和to[i]间的边断开后两点间的最短路加上原来两点间的距离取最小值

    原来博主想用tarjan求边双,然后在1号节点所在的边双中跑dij,但时间并没有下去

    还有注意给边编号从2开始,这样i和i^1是一对双向边

    本来一道很有思维量的题被做成了dijkstra模板(好像没人用正解打)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define ll long long
    #define MAXN 10005
    #define MAXM 40005
    using namespace std;
    ll t,n,m,ans=0x3f3f3f3f;
    ll pre[MAXN],tot_e=1,to[MAXM<<1],nxt[MAXM<<1],w[MAXM<<1];
    void add(ll u,ll v,ll d){
    	tot_e++,to[tot_e]=v,nxt[tot_e]=pre[u],pre[u]=tot_e,w[tot_e]=d;
    }
    ll dis[MAXN];
    priority_queue< pair<ll, ll> > q;
    bool visit[MAXN];
    void dijkstra(ll x){
    	memset(dis,0x3f,sizeof(dis));
    	dis[x]=0;
    	memset(visit,0,sizeof(visit));
    	q.push(make_pair(-dis[x],x));
    	while(!q.empty()){
    		ll y=q.top().second;q.pop();
    		if(visit[y]) continue;
    		visit[y]=1;
    		for(ll i=pre[y];i;i=nxt[i]){
    			ll v=to[i],z=w[i];
    			if(dis[v]>dis[y]+z){
    				dis[v]=dis[y]+z;
    				q.push(make_pair(-dis[v],v));
    			}
    		}
    	}
    }
    int main(){
    	scanf("%lld",&t);
    	while(t--){
    		scanf("%lld%lld",&n,&m);
    		for(ll i=1,u,v,d;i<=m;i++){
    			scanf("%lld%lld%lld",&u,&v,&d);
    			add(u,v,d),add(v,u,d);
    		}
    		for(ll i=pre[1];i;i=nxt[i]){
    			ll temp=w[i];
    			w[i]=w[i^1]=0x3f3f3f3f;
    			dijkstra(1);
    			ans=min(ans,dis[to[i]]+temp);
    			w[i]=w[i^1]=temp;
    		}
    		if(ans==0x3f3f3f3f) ans=-1;
    		printf("%lld
    ",ans);
    		ans=0x3f3f3f3f;
    		tot_e=1;
    		memset(pre,0,sizeof(pre));
    	}
    	return 0;
    }
    
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<queue>
      5 #define ll long long
      6 #define MAXN 10005
      7 #define MAXM 40005
      8 using namespace std;
      9 ll t,n,m,ans=0x3f3f3f3f;
     10 ll pre[MAXN],tot_e=1,to[MAXM<<1],nxt[MAXM<<1],w[MAXM<<1];
     11 void add(ll u,ll v,ll d){
     12     tot_e++,to[tot_e]=v,nxt[tot_e]=pre[u],pre[u]=tot_e,w[tot_e]=d;
     13 }
     14 bool vis[MAXM<<1];
     15 void dfs(ll x,ll res){
     16     if(res>ans) return ;
     17     if(x==1){
     18         if(res!=0){
     19             ans=min(ans,res);
     20             return ;
     21         }
     22     }
     23     for(ll i=pre[x];i;i=nxt[i]){
     24         if(!vis[i]){
     25             vis[i]=1,vis[i^1]=1;
     26             dfs(to[i],res+w[i]);
     27             vis[i]=0,vis[i^1]=0;
     28         }
     29     }
     30 }
     31 ll dfn[MAXN],low[MAXN],dfs_order=0;
     32 bool is_bridge[MAXM<<1];
     33 void tarjan(ll x,ll in_edge){
     34     dfn[x]=low[x]=++dfs_order;
     35     for(ll i=pre[x];i;i=nxt[i]){
     36         ll y=to[i];
     37         if(!dfn[y]){
     38             tarjan(y,i);
     39             low[x]=min(low[x],low[y]);
     40             if(low[y]>low[x])
     41                 is_bridge[i]=is_bridge[i^1]=1;
     42         }
     43         else if(i!=(in_edge^1))
     44             low[x]=min(low[x],dfn[y]);
     45     }
     46 }
     47 bool belong[MAXN];
     48 void DFS(int x){
     49     belong[x]=1;
     50     for(int i=pre[x];i;i=nxt[i]){
     51         int y=to[i];
     52         if(belong[y]||is_bridge[i]) continue;
     53         DFS(y);
     54     }
     55 }
     56 ll dis[MAXN];
     57 priority_queue< pair<ll, ll> > q;
     58 bool visit[MAXN];
     59 void dijkstra(ll x){
     60     memset(dis,0x3f,sizeof(dis));
     61     dis[x]=0;
     62     memset(visit,0,sizeof(visit));
     63     q.push(make_pair(-dis[x],x));
     64     while(!q.empty()){
     65         ll y=q.top().second;q.pop();
     66         if(visit[y]) continue;
     67         visit[y]=1;
     68         for(ll i=pre[y];i;i=nxt[i]){
     69             ll v=to[i],z=w[i];
     70             if(dis[v]>dis[y]+z){
     71                 dis[v]=dis[y]+z;
     72                 q.push(make_pair(-dis[v],v));
     73             }
     74         }
     75     }
     76 }
     77 int main(){
     78     scanf("%lld",&t);
     79     while(t--){
     80         scanf("%lld%lld",&n,&m);
     81         if(n==m){
     82             for(ll i=1,u,v,d;i<=m;i++){
     83                 scanf("%lld%lld%lld",&u,&v,&d);
     84                 add(u,v,d),add(v,u,d);
     85             }
     86             dfs(1,0);
     87             if(ans==0x3f3f3f3f) ans=-1;
     88             printf("%lld
    ",ans);
     89             ans=0x3f3f3f3f;
     90             memset(pre,0,sizeof(pre));
     91             tot_e=1;
     92         }else{
     93             for(ll i=1,u,v,d;i<=m;i++){
     94                 scanf("%lld%lld%lld",&u,&v,&d);
     95                 add(u,v,d),add(v,u,d);
     96             }
     97             for(ll i=1;i<=n;i++){
     98                 if(!dfn[i]) tarjan(i,0);
     99             }
    100             DFS(1);
    101             for(ll i=pre[1];i;i=nxt[i]){
    102                 if(is_bridge[i]||!belong[to[i]]) continue;
    103                 ll temp=w[i];
    104                 w[i]=w[i^1]=0x3f3f3f3f;
    105                 dijkstra(1);
    106                 ans=min(ans,dis[to[i]]+temp);
    107                 w[i]=w[i^1]=temp;
    108             }
    109             if(ans==0x3f3f3f3f) ans=-1;
    110             printf("%lld
    ",ans);
    111             ans=0x3f3f3f3f;
    112             tot_e=1,dfs_order=0;
    113             memset(pre,0,sizeof(pre));
    114             memset(dfn,0,sizeof(dfn));
    115             memset(is_bridge,0,sizeof(is_bridge));
    116         }
    117     }
    118     return 0;
    119 }
    tarjan的复杂算法

     更多算法:

    https://www.cnblogs.com/Juve/articles/11220105.html

  • 相关阅读:
    使用VS2005搭建典型高效的SharePoint开发环境,提高生产效率,包含远程调试,自动部署 无为而为
    该死的Windows 2003 Server DMA设置,然我刻录DVD这么慢,终于找到办法了 无为而为
    听说Team Foundation Server 繁體中文版於 2006.04.28 RTM ,不知道微软中国的工作做得如何? 无为而为
    [软件开发过程]反模式:简单的部分留在需求人员的脑海中,只描述最复杂的部分给我们听 无为而为
    软件过程改进(SPI)常见反模式:第22条军规 无为而为
    在WebPart中上传图片到SharePoint图片库,读取Exif信息到图片的自定义属性 无为而为
    SQL Server 2005 Service Pack 1正式发布了,我想起,有人说,微软的软件至少要等到出了SP1才能用,那么现在可以用SQL2005了 无为而为
    可以下载Microsoft ISA Server 2006 试用版了,网管需要关注 无为而为
    超女带给我们什么? 无为而为
    Asp.net Url改写方法——采用HttpModules(转)
  • 原文地址:https://www.cnblogs.com/Juve/p/11220111.html
Copyright © 2011-2022 走看看