【BZOJ3047&2125】Freda的傳呼機
Description
為了 隨時 與 rainbow快速交流, Freda製造了 兩部傳呼機 。Freda和 rainbow所在的地方有N座房屋、M條雙向 光纜 。每條光纜連線兩座房屋, 傳呼機發出的訊號只能沿著光纜傳遞,並且 傳呼機的訊號 從光纜的其中一端傳遞到另需要花費 t單位時間 。現在 Freda要 進行 Q次試驗, 每次選取兩座房屋,並想知道 傳呼機的訊號在這兩座房屋之間傳遞 至少需 要多長時間。 Freda 和 rainbow簡直弱爆了有木有T_TT_T ,請你幫他們吧……
N座房屋 通過光纜 一定是連通的, 並且這 M條光纜有以下三類連線情況:
A:光纜不形成環 ,也就是光纜僅 有 N-1條。(30%的資料)
B:光纜只 形成一個環,也就是光纜 僅有 N條。(50%的資料)
C:每條光纜僅在一個環中。(10%資料N,M較小,10%資料N,M較大)
Solution
先看A類資料,顯然樹上
再看一下B類資料,環套樹,我們考慮拆掉環。
搜尋一遍把環邊找出來,特殊處理環邊連線的兩個點到所求兩點的距離即可。
對於C類資料,仙人掌圖。
於是我們可以考慮將環拆散,對於每個環,我們找出它們的環頂(這裡環頂的定義是進入該環必須經過的點,注意,環頂不屬於任何環,因為它可以被多個環包含),然後把環頂向這個環上的點連一條邊,邊權為該點到環頂的最短路。
具體實現就是開個棧,處理每個環上的點經過環的兩條路徑的距離即可。
然後原圖就變成一棵樹了,是不是覺得很簡單了!
然而,如果我們直接像A類資料那樣的話,會出現一個問題:
我們看,如果
這時,我們先前統計的環上的兩條路徑就派上用場了。
記兩條路徑分別為
所以,我們求
注意細節。
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 20010
#define M 40010
using namespace std;
int to[M],next[M],last[M],val[M],num=0;
int nt[M],nn[M],nl[M],nv[M],cnt=0;
int dfn[N];
int top=0;
int f[N][15],g[N][15];
int fa[N];
int c1[N],c2[N];
int bl[N],zx[N];
int zz=0;
int d[N];
struct stack{
int x,s;
}st[N];
int tt=0;
int abs(int x)
{
return x<0?-x:x;
}
void link(int x,int y,int c)
{
num++;
to[num]=y;
next[num]=last[x];
last[x]=num;
val[num]=c;
}
void nlink(int x,int y,int c)
{
cnt++;
nt[cnt]=y;
nn[cnt]=nl[x];
nl[x]=cnt;
nv[cnt]=c;
}
void dfs(int x)
{
dfn[x]=++tt;
for(int i=last[x];i;i=next[i])
{
int v=to[i];
if(v!=fa[x] && !dfn[v])
{
fa[v]=x;
top++;
st[top].x=v;
st[top].s=val[i];
dfs(v);
}
else if(v!=fa[x] && dfn[v]<dfn[x])
{
zz++;
int p=top,tmp=val[i];
while(st[p].x!=v && p)
{
c1[st[p].x]=tmp;
tmp+=st[p].s;
p--;
}
tmp=st[p+1].s;
fo(i,p+1,top)
{
zx[st[i].x]=v;
bl[st[i].x]=zz;
c2[st[i].x]=tmp;
int jx=min(c1[st[i].x],c2[st[i].x]);
nlink(st[i].x,v,jx);
nlink(v,st[i].x,jx);
tmp+=st[i+1].s;
}
}
}
top--;
}
bool vis[N];
void cxlb(int x)
{
vis[x]=true;
for(int i=last[x];i;i=next[i])
{
int v=to[i];
if(v!=fa[x] && !vis[v])
{
if((bl[x]!=bl[v] || !bl[x] && !bl[v]) && zx[v]!=x && zx[x]!=v)
{
nlink(x,v,val[i]);
nlink(v,x,val[i]);
}
cxlb(v);
}
}
}
int sbll=0;
void find(int x)
{
for(int i=nl[x];i;i=nn[i])
{
int v=nt[i];
if(v!=f[x][0])
{
f[v][0]=x;
g[v][0]=nv[i];
d[v]=d[x]+1;
find(v);
}
}
}
int lca(int x,int y)
{
int tmp=0;
if(d[x]>d[y]) swap(x,y);
fd(i,14,0)
while(d[f[y][i]]>=d[x])
tmp+=g[y][i],y=f[y][i];
if(x==y) return tmp;
fd(i,14,0)
while(f[x][i]!=f[y][i])
{
tmp+=g[x][i]+g[y][i];
x=f[x][i];
y=f[y][i];
}
if(x!=y && bl[x] && bl[x]==bl[y]) tmp+=min(min(c1[x]+c2[y],c1[y]+c2[x]),min(abs(c2[x]-c2[y]),abs(c1[x]-c1[y])));
else tmp+=g[x][0]+g[y][0];
return tmp;
}
int main()
{
int n,m,q;
cin>>n>>m>>q;
fo(i,1,m)
{
int x,y,t;
scanf("%d %d %d",&x,&y,&t);
link(x,y,t);
link(y,x,t);
}
dfs(1);
cxlb(1);
find(1);
d[0]=-1;
fo(j,1,14)
fo(i,1,n)
{
f[i][j]=f[f[i][j-1]][j-1];
g[i][j]=g[i][j-1]+g[f[i][j-1]][j-1];
}
fo(i,1,q)
{
int x,y;
scanf("%d %d",&x,&y);
printf("%d\n",lca(x,y));
}
}
相關推薦
【BZOJ3047&2125】Freda的傳呼機
Description 為了 隨時 與 rainbow快速交流, Freda製造了 兩部傳呼機 。Freda和 rainbow所在的地方有N座房屋、M條雙向 光纜 。每條光纜連線兩座房屋, 傳呼機發出的訊號只能沿著光纜傳遞,並且 傳呼機的訊號 從光纜的其
[JZOJ3395]【NOIP2013模擬】Freda的傳呼機
Description 為了 隨時 與 rainbow快速交流, Freda製造了 兩部傳呼機 。Freda和 rainbow所在的地方有N座房屋、M條雙向 光纜 。每條光纜連線兩座房屋, 傳呼機發出的訊號只能沿著光纜傳遞,並且 傳呼機的訊號 從光纜的其
【矩陣乘】【DP】【codevs 1305】Freda的道路
1305 Freda的道路 時間限制: 1 s 空間限制: 128000 KB 題目等級: 大師 Master 題目描述 Description Freda要到Rainbow的城堡去玩了。我們可以認為兩座城堡位於同一條數軸上,Freda的城堡座標是
【BZOJ3470】Freda’s Walk 概率與期望
space 現在 pre -c 我們 mil pop 小數 ble 【BZOJ3470】Freda’s Walk Description 雨後的Poetic Island空氣格外清新,於是Freda和Rainbow出來散步。 Poetic Island的
【解題報告】openjudge Freda的越野跑 資料結構與演算法mooc 內排序
描述 Freda報名參加了學校的越野跑。越野跑共有N人蔘加,在一條筆直的道路上進行。這N個人在起點處站成一列,相鄰兩個人之間保持一定的間距。比賽開始後,這N個人同時沿著道路向相同的方向跑去。換句話說,
【長期更新】Ubuntu常用命令備忘錄
err bsp ubuntu lib ubunt clas apt 問題 error Error Could not get lock /var/lib/dpkg/lock 出現這個問題可能是有另外一個程序正在運行,導致資源被鎖不可用。而導致資源被鎖的原因可能是上次運行安
【linux系列】vmware12pro安裝centos7
ping entos 配置 行編輯 rip 無法 conf 解決 config 安裝參考:http://blog.csdn.net/guin_guo/article/details/49403889 安裝完成之後ip還是不成功無法連接網絡: 進入/etc/sysconfig
【滲透測試】NSA Windows 0day漏洞+修復方案
技術 數據 pos 創建 前段時間 更新 服務 主機 ima 這個漏洞是前段時間爆出來的,幾乎影響了全球70%的電腦,不少高校、政府和企業都還在用Windows服務器,這次時間的影響力堪稱網絡大地震。 ------------------------------------
【C語言】統計數字在排序數組中出現的次數
語言 個數 統計 ret r+ () class tdi times //數字在排序數組中出現的次數。 //統計一個數字在排序數組中出現的次數。比如:排序數組{1,2,3,3,3,3,4,5}和數字3,因為3出現了4次,因此輸出4. #include <stdio
BZOJ 2288 【POJ Challenge】生日禮物(貪心+優先隊列)
ace urn ons target challenge pri 最大 font return 【題目鏈接】 http://www.lydsy.com/JudgeOnline/problem.php?id=2288 【題目大意】 給出一列數,求最多取m段
【福利季】《手機歷史漫談》
操作 歷史 三國殺 山寨 真的 時間 外觀 pan 多人 本文地址 原文地址--微信 點擊關註 微信公眾號 手機眾生相 手機大家都不陌生,不管你拿的是高逼格的蘋果手機,還是親民的安卓手機,甚至你固執地懷舊拿著諾基亞的手機,都無
【文學文娛】《西遊記--悼念楊潔》
width idt c# 陽光 ica 自然 provider div 吸引 本文地址 原文地址--微信 點擊關註微信公眾號 西遊·電視劇 寫作起因 說起《西遊記 》,你首先想到的是什麽?是嫉惡如
poj 1915 Knight Moves 【雙向bfs】
ask blank time problem one sum for urn == Knight Moves Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 22121 Acc
【BZOJ1935/4822】[Shoi2007]Tree 園丁的煩惱/[Cqoi2017]老C的任務 樹狀數組
tchar get ont n+1 div 區域 spa 都是 struct 題意:兩道題差不多,都是給你一堆平面上的點,每個點有權值,然後m次詢問求某一矩形區域內的點權和 題解:先離散化,然後將詢問拆成左右兩條線段,然後將點和這些線段一起按x坐標排序,在y軸上維護樹狀數
HDU1251 統計難題 【trie樹】
courier ava 自己的 while onos ets ctrl pan alloc 統計難題 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Other
【Cocos-2dx】使用Visual Studio2017 編譯Cocos-2dx 3.15
工具 python spin 分享 error 3.1 soft bsp cocos2d-x 1.Visual Studio2017是微軟今年更新的VS版本,UI看著比之前的更養眼了。推薦從這個網站下載最新的安裝程序:https://www.visualstudio.com
【vue.js】入門
emp 寫到 logs 組件 images href one mooc 渲染 慕課網視頻學習筆記:http://www.imooc.com/learn/694 1.將html、js、css寫到一個後綴名.vue的文件中,區分這三種類型是通過<template>、
【Ensemble methods】組合方法&集成方法
zed 加權 最好 rdquo ear 整合 表示 ensemble st算法 機器學習的算法中,討論的最多的是某種特定的算法,比如Decision Tree,KNN等,在實際工作以及kaggle競賽中,Ensemble methods(組合方法)的效果往往是最好的,
【HDU 5305】Friends 多校第二場(雙向DFS)
tor typedef type clu name article using ring eof 依據題意的話最多32條邊,直接暴力的話 2 ^ 32肯定超時了。我們能夠分兩次搜索時間復雜度降低為 2 * 2 ^ 16 唯一須要註意的就是對眼下狀態的哈希處理。 我採用
python16_day15【Django入門】
response 最簡 ext tcp inf star -1 解析 為我 一、Django基本 1.什麽是框架 框架,即framework,特指為解決一個開放性問題而設計的具有一定約束性的支撐結構,使用框架可以幫你快速開發特定的系統,簡單地說,就是你用別人搭建好的舞臺