…………仙人掌啊,亦可赛艇
…………好嘛…………写的欲仙欲死23333
前几天考试的题233今天终于过了
根据某blog,仙人掌是植物,所以当成树来做就好了【xxx
于是遇到环的话,吧环顶当成环上其他节点的LCA,连上边长为这个点到环顶的距离的边,在新的树上跑树上路径长度就好了。
这样建树的话还可以知道是从哪个节点进入环的
然而如果是出现了LCA是某个环的环顶的话,显然这样可能不是最优的,于是对于环上的两个点,显然距离是两半二选一,于是记录一下按照找环时遍历的顺序,得到的节点和环顶的距离,相减后和它的补取个min就好了
啊顺便 这个大爷 的码风我喜欢23333【找到个码风相近的人不容易啊【虽然现在我的码风越来越毒瘤了2333
啊…………WA了一年,最后发现…………缩环标记环顶的时候写崩了2333
我是在找完环之后再补全原树上的边的,于是GG了
在dfs遍历找环的时候,如果遇到返祖边(假设指向aim),应该把当前整个栈里的元素的环顶标记成aim。但是并不应该对aim进行操作(因为仙人掌的话,一个节点可以在多个环中),所以在这个时候,aim并没有标记环顶。
显然应该在dfs结束之后,对于所有没有标记环顶的节点,把环顶标记成自己(如果是单节点的话就当成一元环嘛233),这样再复原原图中的边的时候就不会出锅
代码【码力太渣写到想死x】【不过A了真的迷之快♂感啊2333】【lxl大爷表示:你们啊naive,我一遍就A了】
【嗯读入优化是个好东西啊23333】
↓从上到下是nzhtl1477大爷的fread,fwrite;咸鱼读优;没有优化
总之谢谢lxl的读入输出优化模板w
#include
#define MAXN 10005
using namespace std; int n,m,q;
//==================================================
struct io_t{
char op[3<<20];
char* s;
int a[24];
char ed[1<<20];
char* t;
io_t():s(op),t(ed){
fread(s,1,
sizeof op,stdin);
}
~io_t(){
fwrite(ed,1,
t-ed,stdout);
}
void scan(char* q){
while(*s<48)
++s;
while(*s>32)
*q++=*s++;
*q=0;
}
void print(const
char* q){
while(*q)
*t++=*q++;
*t++=10;
}
int scan(){
static int v,j;
v=0,j=1;
while(*s<48)
j=*s++^45;
do
v=v*10+*s++-48;
while(*s>32);
return j?v:-v;
}
template< class T >
void print( register T v){
static int* q=a;
if(!v)*t++=48;
else{
if(v<0)
*t++=45,
v*=-1;
while(v)
*q++=v%10+48,
v/=10;
while(q!=a)
*t++=*--q;
}
*t++=10;
}
}io;
//==========================================================
struct t1{
int to,nxt,lth;
int tag;
t1(){}
t1(int to,int nxt,int lth):to(to),nxt(nxt),lth(lth){}
}edge[MAXN<<2],edge_2[MAXN<<2]; int cnt_edge=1,cnt_edge_2=0;
int fst[MAXN],fst_2[MAXN];
inline void addedge(int x,int y,int l){
edge[++cnt_edge]=t1(y,fst[x],l);
fst[x]=cnt_edge;
edge[++cnt_edge]=t1(x,fst[y],l);
fst[y]=cnt_edge;
}
inline void addedge_2(int x,int y,int l){
edge_2[++cnt_edge_2]=t1(y,fst_2[x],l);
fst_2[x]=cnt_edge_2;
edge_2[++cnt_edge_2]=t1(x,fst_2[y],l);
fst_2[y]=cnt_edge_2;
}
//=======================================================
int tot[MAXN];
int root[MAXN];
int dis[MAXN];
int dis_to_top[MAXN];
int dfn[MAXN],cnt_dfs=0;
int siz[MAXN];
int is_root[MAXN];
int col[MAXN],cnt_col=0;
int stk[MAXN],top_s=0;
int anc[MAXN][18];
void dfs(int now,int pre){
dfn[now]=++cnt_dfs;
stk[++top_s]=now;
anc[now][0]=pre;
for(register int tmp=fst[now];tmp;tmp=edge[tmp].nxt){
int aim=edge[tmp].to;
if(aim==pre) continue;
if(dfn[aim]){
if(dfn[aim]i) printf("( %d , %d ,lth = %d)\n",i,edge_2[j].to,edge_2[j].lth);
// puts("\n");
for(int i=1;i<=n;++i) if(!root[i]) root[i]=i;
for(int i=1;i<=n;++i)
for(register int j=fst[i];j;j=edge[j].nxt){
int aim=edge[j].to;
if((root[i]^root[aim])&&(!edge[j].tag)&&(i^root[aim])&&(aim^root[i]))
addedge_2(i,aim,edge[j].lth),edge[j].tag=edge[j^1].tag=1;
}
// for(int i=1;i<=n;++i)
// for(int j=fst_2[i];j;j=edge_2[j].nxt)
// if(edge_2[j].to>i) printf("( %d , %d ,lth = %d)\n",i,edge_2[j].to,edge_2[j].lth);
memset(anc,0,sizeof anc);
memset(dis,0,sizeof dis);
dpt[1]=1;
dfs_2(1);
// for(int i=1;i<=n;++i) printf("%d\n",dis[i]);
for(int i=1;i<=q;++i){
read_x=read(),read_y=read();
// printf("dis ( %d , %d ) = ",read_x,read_y);
print(inqry(read_x,read_y));
}
return 0;
}