zoukankan      html  css  js  c++  java
  • 洛谷4366——最短路(dijkstra,思维,异或)

    题目大意
    给定一个n个点,m条边的图,每条边有边权,而每个点(i)也可以直接到达(j),代价是(i xor j),给定一个S和T,求S到T的最小代价
    其中(nle100000,mle100000)

    一看这个数据范围,我们就知道显然不能建图~
    那么就需要一点小技巧了

    这里写图片描述

    就是说,一条边可以由好几部分的边组合而成,而且代价还是相等的

    注意 0 号结点也需要考虑(有可能两个节点编号按位与为0 ),并把异或值控制在 n 以内(出了 n 范围的点一定可以用 0号节点解决)

    所以对于节点(x)我们只需要将他向 (x xor 2^k)连边就可以~
    因为通过这个中转节点,他就可以到其他的能到的点,而且权值也是一样的

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<map>
    #include<queue>
    #include<vector>
    #define pa pair< int , int >
    using namespace std;
    
    inline int read()
    {
       int x=0,f=1;char ch=getchar();
       while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
       while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
       return x*f;
    }
     
    const int maxn = 1e5+1e2;
    const int maxm = 4e6+1e2;
    
    int point[maxn],nxt[maxm],to[maxm],val[maxm];
    int n,m;
    int vis[maxn],dis[maxn];
    int cnt;
    int s,t;
    priority_queue<pa,vector<pa>,greater<pa> > q;
    
    void addedge(int x,int y,int w)
    {
    	nxt[++cnt]=point[x];
    	to[cnt]=y;
    	val[cnt]=w;
    	point[x]=cnt;
    }
    
    int c;
    
    void dijkstra(int s)
    {
    	memset(dis,127/3,sizeof(dis));
    	memset(vis,0,sizeof(vis));
    	dis[s]=0;
    	q.push(make_pair(0,s));
    	while (!q.empty())
        {
        	int x = q.top().second;
        	q.pop();
        	if (vis[x]) continue;
        	vis[x]=1;
        	for (int i=point[x];i;i=nxt[i])
        	{
        		int p = to[i];
        		if (dis[p]>dis[x]+val[i])
        		{
        			dis[p]=dis[x]+val[i];
        			q.push(make_pair(dis[p],p));
    			}
    		}
    	}
    }
    
    int main()
    {
      scanf("%d%d%d",&n,&m,&c);
      for (int i=1;i<=m;++i)
      {
      	 int x=read(),y=read(),w=read();
      	 addedge(x,y,w);
      }
      for (int i=0;i<=n;++i)
      {
      	 for (int j=1;j<=n;j<<=1)
      	 {
      	 	int tmp = (i^j);
      	 	if (tmp>n) continue;
      	 	addedge(i,tmp,j*c);
    	   }
      }
      cin>>s>>t;
      dijkstra(s);
      cout<<dis[t]<<endl;
      return 0;
    }
    
    
  • 相关阅读:
    POJ 3140 Contestants Division (树dp)
    POJ 3107 Godfather (树重心)
    POJ 1655 Balancing Act (树的重心)
    HDU 3534 Tree (经典树形dp)
    HDU 1561 The more, The Better (树形dp)
    HDU 1011 Starship Troopers (树dp)
    Light oj 1085
    Light oj 1013
    Light oj 1134
    FZU 2224 An exciting GCD problem(GCD种类预处理+树状数组维护)同hdu5869
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10160753.html
Copyright © 2011-2022 走看看