码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 4289 TAX —— 点边转化

时间:2018-10-17 11:09:17      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:int   原来   opera   i++   long   online   end   fine   注意   

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4289

把边转化成点,同一个原有点相连的边中,边权小的向大的连差值的边,大的向小的连0的边;

一开始想的是给每个新点记一个点权是这个点(边)原来的权,走到它时先加上点权,因为要在原图上经过这条边还是要花费边权;

但是这样在原图中的边之间转移时会把它们的边权都加上,就不对了;

所以应该是把原图的边进一步拆成两个点,两端点的集合各加入一个,这两点之间连原边权的边;

题目上什么也没说...总之 dis 是 long long 的;

如果直接把刚才存边用的结构体放进 queue,就要注意把结构体的 w 定义成 ll,而且一定注意结构体内部定义变量的顺序!因为 (N){..., ...} 的写法是强调顺序的!

——然后发现这道题三个月前做过-_- https://www.cnblogs.com/Zinn/p/9326302.html

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define pb push_back
using namespace std;
typedef long long ll;
int const xn=2e5+5,xm=1e5+5;
int n,m,s,t,hd[xn<<1],ct,to[xn<<3],nxt[xn<<3],w[xn<<3];
ll dis[xn<<1];
bool vis[xn<<1];
struct N{
  ll w; int id;//ll(dis)
  bool operator < (const N &y) const
  {return w<y.w;}
};
vector<N>v[xm];
priority_queue<N>q;
int rd()
{
  int ret=0,f=1; char ch=getchar();
  while(ch<0||ch>9){if(ch==-)f=0; ch=getchar();}
  while(ch>=0&&ch<=9)ret=(ret<<3)+(ret<<1)+ch-0,ch=getchar();
  return f?ret:-ret;
}
void add(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; w[ct]=z; hd[x]=ct;}
void dij()
{
  while(q.size())
    {
      int x=q.top().id; q.pop();
      if(vis[x])continue; vis[x]=1;
      for(int i=hd[x],u;i;i=nxt[i])
    {
      if(dis[u=to[i]]>dis[x]+w[i])
        dis[u]=dis[x]+w[i],q.push((N){-dis[u],u});
    }
    }
}
int main()
{
  n=rd(); m=rd(); s=0; t=2*m+1;
  for(int i=1,x,y,z;i<=m;i++)
    {
      x=rd(); y=rd(); z=rd();
      v[x].pb((N){z,i}); v[y].pb((N){z,i+m});
      add(i,i+m,z); add(i+m,i,z);
    }
  for(int i=0;i<v[1].size();i++)add(s,v[1][i].id,v[1][i].w);
  for(int i=0;i<v[n].size();i++)add(v[n][i].id,t,0);//0
  for(int i=1;i<=n;i++)
    {
      sort(v[i].begin(),v[i].end());
      for(int j=1;j<v[i].size();j++)
    add(v[i][j-1].id,v[i][j].id,v[i][j].w-v[i][j-1].w),add(v[i][j].id,v[i][j-1].id,0);
    }
  memset(dis,0x3f,sizeof dis);
  dis[s]=0; q.push((N){0,s});
  dij(); 
  printf("%lld\n",dis[t]);
  return 0;
}

 

bzoj 4289 TAX —— 点边转化

标签:int   原来   opera   i++   long   online   end   fine   注意   

原文地址:https://www.cnblogs.com/Zinn/p/9802183.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!