uoj#30. 【CF Round #278】Tourists

題意:

C 國有 n 座城市,編號 1,2,3,…,n,構成一張無向圖。每座城市都會賣菜,城市 i 菜價爲Pi。你需 要維護一下兩種操作:

1 x b:城市 x 的菜價變爲 b

2 u v:小 R 從 u 走到 v,你需要幫他規劃一條簡單路徑(即每個點最多經過 1 次),使得這條路徑 上菜價最便宜的點的菜價最便宜,你只需要輸出最便宜的菜價即可。

由於一個點雙中所有點兩兩一定都能不經過重複點走到,因此只需縮點,構成圓方樹,然後求樹上兩點之間鏈上最小值,用樹鏈剖分即可。

這裏注意:對於一個點修改,只需修改其原點以及其1父節點(方節點)即可,這樣相當於以及修改了一個點分塊,但要注意,由於點分塊中有一個圓點是方點的father而不是son,所以當兩點之間鏈上lca爲方點時,要特判其父節點(及圓點)。

對於圓方樹,就看這個鏈接吧,主要實現點雙縮點功能

代碼:

void tarjan(int x,int fa)
{
  t[++s1]=x;
  dfn[x]=low[x]=++times;
  for (int i=head1[x];i;i=nxt1[i])
  {  int v=to1[i];
  if (v==fa) continue;//然而並不知道這一條要不要加(待續)
  	if (!dfn[v]) {tarjan(v,x);  low[x]=min(low[v],low[x]);
  	              if (low[v]>=dfn[x])
					{  cnt++;
					  while (t[s1]!=x)
					  {  add2(cnt,t[s1]);
					     add2(t[s1],cnt);
					   // cout<<z<<' '<<t[s1]<<endl;
					     s1--;}
					      add2(cnt,t[s1]);
						  add2(t[s1],cnt);
					// cout<<z<<' '<<t[s1]<<endl;
					 } 
					}
  	             else {  low[x]=min(dfn[v],low[x]); }
  }
}

總代碼(然而uoj上掛了,不知道爲什麼,未完)

#include<bits/stdc++.h>
using namespace std;
const int N=1000100;
const int inf= 0x3f3f3f3f;
struct node/***實現刪除小根堆中任意數*/
{  priority_queue<int,vector<int>,greater<int> > q1,q2;
   void erase(int x) {  q2.push(x);}
   void insert(int x) { q1.push(x);}
   int top(){
   	  while (!q2.empty() && q2.top()==q1.top()) {q1.pop();q2.pop();}
   	  return q1.top();
   }
}s[N];
char k;
int n,m,min1,cnt1,x,b,y,tot1,z,cnt,s1,q,tot,times,v,id[N],f[N],size[N],top[N],child[N],zhi[N],d[N],cost[N],t[N],cut[N],to[N],low[N],dfn[N],head[N],nxt[N],to1[N],head1[N],nxt1[N];
inline int read()
{
    int k=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        k=k*10+ch-'0';
        ch=getchar();
    }
    return k*f;
}
void add(int x,int y)
{  nxt1[++tot]=head1[x];
   head1[x]=tot;
   to1[tot]=y;
}
void add2(int x,int y)
{  nxt[++tot1]=head[x];
   head[x]=tot1;
   to[tot1]=y;
}
void tarjan(int x,int fa)
{
  t[++s1]=x;
  dfn[x]=low[x]=++times;
  for (int i=head1[x];i;i=nxt1[i])
  {  int v=to1[i];
  if (v==fa) continue;
  	if (!dfn[v]) {tarjan(v,x);  low[x]=min(low[v],low[x]);
  	              if (low[v]>=dfn[x])
					{  cnt++;
					  while (t[s1]!=x)
					  {  add2(cnt,t[s1]);
					     add2(t[s1],cnt);
					   // cout<<z<<' '<<t[s1]<<endl;
					     s1--;}
					      add2(cnt,t[s1]);
						  add2(t[s1],cnt);
					// cout<<z<<' '<<t[s1]<<endl;
					 } 
					}
  	             else {  low[x]=min(dfn[v],low[x]); }
  }
}
void dfs(int x,int fa)
{
	if (x<=n && fa) s[fa].insert(cost[x]);
	size[x]=1;f[x]=fa;d[x]=d[fa]+1;
    int max1=0;
	for (int i=head[x];i;i=nxt[i])
	{
	   int v=to[i];
	   if (v!=fa)
	   {  dfs(v,x);
	      if (size[v]>max1) {  max1=size[v]; child[x]=v;  }
	     size[x]=size[x]+size[v];}
	}
}
void dfs2(int x,int fa)
{ 
    id[x]=++cnt1;
	top[x]=fa;
	if (child[x]) dfs2(child[x],fa);
	for (int i=head[x];i;i=nxt[i])
	{   int  v=to[i];
	   if (v!=child[x] && v!=f[x])
	   { dfs2(v,v); }
	}
}
void change(int a1,int l,int r,int x,int y)
{
  if (l==r) {zhi[a1]=y; return;}
  int mid=(l+r)>>1;
  if (x<=mid)  change(a1*2,l,mid,x,y);
          else change(a1*2+1,mid+1,r,x,y);
  zhi[a1]=min(zhi[a1*2],zhi[a1*2+1]); 
}
int  query(int a1,int l,int r,int x,int y)
{
  if (l==r) {return zhi[a1];}
  if (x<=l && y>=r) { return zhi[a1];}
  int mid=(l+r)>>1;
  if (y<=mid)  return query(a1*2,l,mid,x,y);
  if (x>mid) return query(a1*2+1,mid+1,r,x,y);
  return min(query(a1*2,l,mid,x,y),query(a1*2+1,mid+1,r,x,y));
}
int  tcd(int a,int b)
{  min1=inf;
	  while (top[a]!=top[b])
	  { if (d[top[a]]<d[top[b]]) swap(a,b);
	    min1=min(min1,query(1,1,cnt,id[top[a]],id[a]));
	    a=f[top[a]];
	  }
	  if (d[a]<d[b])  swap(a,b);  
	  min1=min(min1,query(1,1,cnt,id[b],id[a]));
   if (b>n)  min1=min(min1,cost[f[b]]);
   return min1;
}
int main()
{
	cin>>n>>m>>q;
	for (int i=1;i<=n;i++)  cost[i]=read();
	for (int i=1;i<=m;i++)	{  cin>>x>>y;  add(x,y); add(y,x);}
	cnt=n;
	tarjan(1,1);
	dfs(1,0);dfs2(1,1);
	//cout<<z<<endl;
//cnt=z;
	memset(zhi,0x3f,sizeof(zhi));
    for (int i=1;i<=n;i++) change(1,1,cnt,id[i],cost[i]);
	for (int i=n+1;i<=cnt;i++)  
	{
	  change(1,1,cnt,id[i],s[i].top());
	}
	for (int i=1;i<=q;i++)
	{  cin>>k;
	   if (k=='C') {  cin>>x>>b; change(1,1,cnt,id[x],b);
	                if (f[x]) {  
					            s[f[x]].erase(cost[x]);
					           // cout<<cost[x]<<endl;
					           s[f[x]].insert(b);
					           //cout<< s[f[x]].top()<<endl;
							   change(1,1,cnt,id[f[x]],s[f[x]].top());
							   }
					cost[x]=b;
				}
				else
				{
					cin>>x>>y;
					cout<<tcd(x,y)<<endl;				
				}
	}	
}

 

發佈了26 篇原創文章 · 獲贊 0 · 訪問量 2732
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章