专项测试 图论1
T1 序列
分块,对每个块重新排序,区间取max就块内二分出能更新到的右端点,然后存一个栈里
为了防止MLE可以在栈内元素超过\(O(\sqrt n)\)时pushdown
修改时的散块和查询时所在的块都要先pushdown
散块修改后重构一下
复杂度\(O(n\sqrt n\log n)\)
坑:当加的数是0时不能算作一次变化
T2 旅行计划
若u,v不在一个联通块里,NIE
若k为奇数,可以u,v之间来回走,答案一定是0
若k为偶数,对于联通块内所有边l1,l2,...,le,使d=gcd(l1,l2,...,le,k),先使所有数除以d,此时存在
\[k_1l_1+k_2l_2+...+k_el_e \equiv1 \pmod k \]因为每条边可以来回走,那么从任意一点出发都可以经过所有边两次回到自身(dfs树),也就是存在模k意义下为2的环
那么若存在一条u->v的偶数路径,可以一直跑环直到k的倍数,答案是0
若只存在u->v的奇数路径,跑环直到\(a* k-1\),再跑一遍变成\(a* k+1\),然后答案就是1* d
所以问题转换成了寻找偶数路径
偶数路径可以是奇环加奇数路径,或一条简单偶数路径
每个点拆成奇点和偶点,并查集维护,u->v为奇就奇点连偶点,否则偶连偶,奇连奇
若满足条件那么u,v的奇点在同一并查集里
T3 hack
限制是每条路径上只能割一条边
缩成DAG后建出0->n-1的分层图,不难发现若没有层间边和反向边,直接跑最小割就是答案
若u->v是一条层间边或反向边,s->u和v->t一定不能同时被割
连一条v->u的inf边即可
坑:不保证联通,缩点之后建边0会乱连
代码
T1
#include
using namespace std;
#define il inline
#define int long long
const int inf=1e15;
const int N=1e5+11;
const int siz=201;
struct opt_{int r;int val;}opt[511][511];
struct loc_{
int val;
int num,id;
friend bool operator<(loc_ a,loc_ b){return a.val'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
return s*w;
}
il char readc()
{
char ch=getchar();
while(ch!='Q'&&ch!='A'&&ch!='M') ch=getchar();
return ch;
}
void pushdown(int &x)
{
if(!top[x]) return;
int num=0;
int i;
int val=opt[x][top[x]].val;
while(top[x])
{
++num;
for(i=opt[x][top[x]].r;i>opt[x][top[x]-1].r;--i) a[i].val=val,a[i].num+=num;
--top[x];
}
return;
}
void add(int &l,int &r,int &val)
{
if(val==0) return;
int i;
int bl=blo[l],br=blo[r];
if(bl==br)
{
pushdown(bl);
for(i=lb[bl];i<=rb[bl];++i) if(a[i].id>=l&&a[i].id<=r) a[i].val+=val,++a[i].num;
sort(a+lb[bl],a+rb[bl]+1);
return;
}
pushdown(bl),pushdown(br);
for(i=lb[bl];i<=rb[bl];++i) if(a[i].id>=l&&a[i].id<=r) a[i].val+=val,++a[i].num;
for(i=lb[br];i<=rb[br];++i) if(a[i].id>=l&&a[i].id<=r) a[i].val+=val,++a[i].num;
sort(a+lb[bl],a+rb[bl]+1);
sort(a+lb[br],a+rb[br]+1);
for(i=bl+1;i
400) pushdown(i);
if(opt[i][top[i]].val+delv[i]>=val) return;
int l=opt[i][top[i]].r+1,r=rb[i],mid,ans=opt[i][top[i]].r;
while(l<=r)
{
mid=(l+r)>>1;
if(a[mid].val+delv[i]=l&&a[i].id<=r&&a[i].val+delv[bl]=l&&a[i].id<=r&&a[i].val+delv[bl]=l&&a[i].id<=r&&a[i].val+delv[br]
T2
#include
using namespace std;
const int N=2e5+11;
int n,m,q;
int f[N],f1[N];
int u[N],v[N],w[N];
int gd[N];
int find(int x){if(x==f[x])return x;return f[x]=find(f[x]);}
int find1(int x){if(x==f1[x])return x;return f1[x]=find1(f1[x]);}
int gcd(int x,int y){if(!y)return x;return gcd(y,x%y);}
void merge(int x,int y){x=find(x),y=find(y);f[x]=y;gd[y]=gcd(gd[y],gd[x]);return;}
void mergej(int x,int y){f1[find1(x+n)]=find1(y),f1[find1(x)]=find1(y+n);return;}
void mergeo(int x,int y){f1[find1(x)]=find1(y),f1[find1(x+n)]=find1(y+n);return;}
inline int read()
{
int s=0;
char ch=getchar();
while(ch>'9'||ch<'0') ch=getchar();
while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
return s;
}
int main()
{
n=read();
m=read();
q=read();
for(int i=1;i<=n;++i) f[i]=f1[i]=i,f1[i+n]=n+i;
for(int x,i=1;i<=m;++i)
{
u[i]=read(),v[i]=read(),w[i]=read();
merge(u[i],v[i]);
x=find(u[i]);
if(gd[x]) gd[x]=gcd(gd[x],w[i]);
else gd[x]=w[i];
}
for(int x,y,z,i=1;i<=m;++i)
{
x=u[i],y=v[i],z=w[i]/gd[find(x)];
if(z&1) mergej(x,y);
else mergeo(x,y);
}
for(int x,y,k,i=1;i<=q;++i)
{
x=read(),y=read(),k=read();
if(find(x)!=find(y)) printf("%s\n","NIE");
else if(find1(x)==find1(y)) printf("%d\n",0);
else printf("%d\n",gcd(k,gd[f[x]]));
}
return 0;
}
T3
#include
using namespace std;
#define il inline
#define int long long
const int N=1e4+11;
const int inf=0x7fffffff;
struct qxxx{int v,next,w;}cc[N];
struct e_{int u,v,w;}e[N];
bool vis[N];
int n,m,s,t;
int d[N];
int dfn[N],st,low[N],f[N],num;
int first[N],cnt,now[N];
stack sta;
queue dui;
il int min_(int x,int y){return x>y?y:x;}
il void qxx(int u,int v,int w){cc[++cnt]={v,first[u],w};first[u]=cnt;return;}
il void add(int u,int v,int w){qxx(u,v,w),qxx(v,u,0);return;}
il int read()
{
int s=0;
char ch=getchar();
while(ch>'9'||ch<'0') ch=getchar();
while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
return s;
}
void tarjan(int x)
{
vis[x]=1;
sta.push(x);
low[x]=dfn[x]=++st;
for(int i=first[x];i;i=cc[i].next)
{
if(!dfn[cc[i].v])
{
tarjan(cc[i].v);
low[x]=min_(low[x],low[cc[i].v]);
}
else if(vis[cc[i].v]) low[x]=min_(low[x],dfn[cc[i].v]);
}
if(low[x]==dfn[x])
{
int tmp;
++num;
do{
tmp=sta.top();
sta.pop();
f[tmp]=num;
vis[tmp]=0;
}while(tmp!=x);
}
return;
}
bool bfs()
{
while(dui.size())dui.pop();
memset(d,0,sizeof(d));
d[s]=1;
now[s]=first[s];
int x;
dui.push(s);
while(dui.size())
{
x=dui.front(),dui.pop();
for(int i=first[x];i;i=cc[i].next)
if(cc[i].w&&!d[cc[i].v])
{
d[cc[i].v]=d[x]+1;
now[cc[i].v]=first[cc[i].v];
dui.push(cc[i].v);
if(cc[i].v==t) return 1;
}
}
return 0;
}
int dinic(int x,int flow)
{
if(x==t) return flow;
int rest=flow,i,k;
for(i=now[x];i;i=now[x]=cc[i].next)
{
if(cc[i].w&&d[cc[i].v]==d[x]+1)
{
k=dinic(cc[i].v,min_(rest,cc[i].w));
if(!k) d[cc[i].v]=0;
rest-=k;
cc[i].w-=k;
cc[i^1].w+=k;
}
if(!rest) break;
}
return flow-rest;
}
signed main()
{
n=read(),m=read();
for(int x,y,z,i=1;i<=m;++i)
{
x=read(),y=read(),z=read();
e[i]={x,y,z};
qxx(x,y,z);
}
tarjan(0);
if(f[0]==f[n-1]){cout<<-1<d[f[y]]) add(f[y],f[x],inf);
}
int maxflow=0,flow;
while(bfs())while(flow=dinic(s,inf))maxflow+=flow;
cout<