//边链表
inline void insert(int u,int v,int w)
{
e[++cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt;
e[cnt].v=w;
}
//vector
vectot<int> G[M];
inline void insert(int u,int v)
{
G[u].push_back(v);
G[v].push_back(u);
}
inline dfs(int x)
{
vis[x]=1;
for(int i=0;i<G[x].size();i++)
{
int v=G[x][i];
if(!vis[v]) dfs(v);
}
}
//遍历
inline dfs(int x,int fa)
{
vis[x]=1;
for(int i=head[x];i;i=e[i].next)
{
if(e[i].to!=fa && !vis[e[i].to])
dfs(e[i].to,x);
}
}
inline bfs(int s)
{
q.push(s);
vis[s]=1;
while(!q.empty())
{
int now=q.front();q.pop();
for(int i=head[now];i;i=e[i].next)
{
if(!vis[e[i].to])
{
q.push(e[i].to);
vis[e[i].to]=1;
}
}
}
}
//最短路
//floyd
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(f[i][j]>f[i][k]+f[k][j])
f[i][j]=f[i][k]+f[k][j];
}
//dijkstra
inline void dijkstra(int s)
{
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >
for(int i=0;i<=n;i++)
dis[i]=inf;
dis[s]=0;q.push(make_pair(dis[s],s);
while(!q.empty())
{
int now=q.top().second;q.pop();
if(vis[now]) continue;
vis[now]=1;
for(int i=head[now];i;i=e[i].next)
if(dis[now]+e[i].v<dis[e[i].to])
{
dis[e[i].to]=dis[now]+e[i].v;
q.push(make_pair(dis[e[i].to],e[i].to));
}
}
}
//spfa
inline void spfa(int s)
{
queue<int> q;
for(int i=1;i<=n;i++)
dis[i]=inf;
q.push(s);
dis[s]=1;
vis[s]=1;
mark[s]++;
while(!q.empty())
{
int now=q.front();q.pop();vis[now]=0;
for(int i=head[now];i;i=e[i].next)
{
if(dis[now]+e[i].v<dis[e[i].to])
{
dis[e[i].to]=dis[now]+e[i].to;
if(!vis[e[i].to])
{
q.push(e[i].to);
mark[e[i].to]++;
if(mark[e[i].to]>=n) return -1;//有负环
vis[e[i].to]=1;
}
}
}
}
}
//并查集
inline int find(int x)
{
if(fa[x]==x) return x;
else return fa[x]=find(fa[x]);
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
int fx=find(x),fy=find(y);
if(fx==fy) continue;
fa[fx]=fy;
}
//kruskal
inline bool cmp(node x,node y)
{
return x.v<y.v;
}
sort(a+1,a+m+1,cmp);
for(int i=1;i<=m;i++)
{
int fx=find(a[i].x),fy=find(a[i].y);
if(fx==fy) continue;
fa[fx]=fy;
++cnt;ans+=a[i].v;
if(cnt==n-1) break;
}
//topsort
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
d[v]++;
}
inline void topsort()
{
int tot=n;
for(int i=1;i<=n;i++)
{
if(!d[i])
{
q.push(i);
tot--;
t[++cnt]=i;
}
}
while(!q.empty())
{
int now=q.front();q.pop();
for(int i=head[now];i;i=e[i].next)
{
d[e[i].to]--;
if(!d[e[i].to])
{
q.push(e[i].to);tot--;
t[++cnt]=e[i].to;
}
}
}
if(tot) return -1;//有负环
}
//tarjan
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
inline void tarjan(int x)
{
dfn[x]=low[x]=++time;
s[++s[0]]=x;
vis[x]=1;
for(int i=head[x];i;i=e[i].next)
{
if(!dfn[e[i].to])
{
tarjan(e[i].to);
low[x]=min(low[x],low[e[i].to]);
}
else if(vis[e[i].to])
low[x]=min(low[x],dfn[e[i].to]);
}
if(dfn[x]==low[x])
{
vis[now]=0;num[bl[now]=++scc]=1;
while(s[s[0]]!=now)
{
vis[s[s[0]]]=0;
bl[s[s[0]]]=scc;
num[scc]++;
s[0]--;
}
s[0]--;
}
}
//割点
//u为割点 u->v
//1.u为树根 且多于一个子树 2.low[v]>=dfn[u]
//桥
//u->v 为桥
//low[v]>dfn[u]
//lca(倍增)
inline void dfs(int now,int fa)
{
for(int i=head[now];i;i=e[i].next)
{
if(e[i].to==fa) continue;
dep[e[i].to]=dep[now]+1;
f[e[i].to][0]=now;
minn[e[i].to][0]=e[i].v;
dfs(e[i].to,now);
}
}
inline void st()
{
for(int i=1;i<=20;i++)
for(int j=1;j<=n;j++)
{
f[j][i]=f[f[j][i-1]][i-1];
minn[j][i]=std::min(minn[j][i-1],minn[f[j][i-1]][i-1]);
}
}
inline int lca(int u,int v)
{
if(dep[u]<dep[v]) swap(u,v);
for(int i=20;i>=0;i--)
if(dep[f[u][i]]>=dep[v])
u=f[u][i];
if(u==v) return u;
for(int i=20;i>=0;i--)
if(f[u][i]!=f[v][i])
u=f[u][i],v=f[v][i];
return f[u][0];
}
//lca(树链剖分)
inline void dfs1(int now)
{
sz[now]++;
for(int i=head[now];i;i=e[i].next)
{
if(dep[e[i].to]) continue;
dep[e[i].to]=dep[now]+1;
fa[e[i].to]=now;
dfs1(e[i].to);
sz[now]+=sz[e[i].to];
}
}
inline void dfs2(int now,int clain)
{
top[now]=clain;
int mxsz=0,pos=0;
for(int i=head[now];i;i=e[i].next)
{
if(fa[e[i].to]==now) continue;
if(sz[e[i].to]>mxsz)
{
pos=e[i].to;
mxsz=sz[e[i].to];
}
}
dfs2(pos,clain);
for(int i=head[now];i;i=e[i].next)
{
if(e[i].to==pos || fa[e[i].to]==now) continue;
dfs2(e[i].to,e[i].to);
}
}
inline int lca(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
//欧拉回路
int cnt=1;
inline void insert(int u,int v)
{
insert1(u,v);
insert1(v,u);
}
inline void dfs(int x)
{
for(int i=head[x];i;i=e[i].next)
{
if(!vis[i])
{
vis[i]=vis[i^1]=1;
dfs(e[i].to);
}
}
s.push_back(x);
}
bool check()
{
for(int i=1;i<=n;i++)
if(d[i]&1) return 0;//不是欧拉回路
return 1;
}
//差分约束系统
//x0+d<=x1 x0->x1 边权为d
//x0+d>=x1 x1-d<=x0 x1->x0 边权为-d
//x0+d=x1 建两条边 x0+d<=x1 x0+d>=x1