考虑到满足欧拉回路的条件是每个点的入度和出度相等。
答案可以二分,对于每个mid建图。
我们考虑如下的建图方式,先把所有的无向边随意定向,计算点的度数。如果此时有奇数度数的点,那么就肯定不存在欧拉回路。
S向入度<出度的点连容量为出度-入度的边,入度>出度的点向T连入度-出度的边,之前的随意定向的无向边提供了调整的机会,假设初始定向u->v,那么连v->u流量为1的边。
在最后我们需要找到欧拉路径即可
【代码】
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e4+5;
int n,m,u[maxn],v[maxn],val1[maxn],val2[maxn];
int fa[maxn],vis[maxn],block;
const int inf=0x3f3f3f3f;
int find(int x)
{
if(x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
int head[2005],tot;
struct edge
{
int to,nxt,v;
}e[maxn<<2],E[maxn<<1];
int S,T,du[maxn];
void add(int x,int y,int val)
{
e[++tot].to=y; e[tot].nxt=head[x]; e[tot].v=val; head[x]=tot;
}
int id[maxn<<1],dis[2005];
bool bfs()
{
memset(dis,-1,sizeof(dis));
queue <int> q;
q.push(S); dis[S]=0;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i;i=e[i].nxt)
{
int to=e[i].to;
if(dis[to]==-1 && e[i].v>0)
{
dis[to]=dis[u]+1;
q.push(to);
}
}
}
return (dis[T]!=-1);
}
int dfs(int x,int flow)
{
if(x==T) return flow;
int res=0;
for(int i=head[x];i;i=e[i].nxt)
{
int to=e[i].to;
if(e[i].v>0 && dis[to]==dis[x]+1)
{
int tmp=dfs(to,min(flow,e[i].v));
flow-=tmp; e[i].v-=tmp; e[i^1].v+=tmp;
res+=tmp;
}
}
if(!res) dis[x]=-1;
return res;
}
int dinic()
{
int res=0;
while(bfs())
{
res+=dfs(S,inf);
}
return res;
}
bool check(int mid)
{
tot=1; memset(head,0,sizeof(head));
memset(du,0,sizeof(du));
for(int i=1;i<=n;i++) fa[i]=i;
S=n+1; T=n+2; block=n;
for(int i=1;i<=m;i++)
{
if(val1[i]<=mid) du[u[i]]--,du[v[i]]++;
if(val2[i]<=mid)
{
id[i]=tot+1;
add(v[i],u[i],1);
add(u[i],v[i],0);
}
if(val1[i]<=mid || val2[i]<=mid)
{
int fu=find(u[i]),fv=find(v[i]);
if(fu!=fv)
{
block--;
fa[fu]=fv;
}
}
}
if(block>1)
return false;
for(int i=1;i<=n;i++) if(du[i]&1) return false;
int maxflow=0;
for(int i=1;i<=n;i++)
{
if(du[i]>0)
{
maxflow+=du[i]/2;
add(S,i,du[i]/2); add(i,S,0);
}
else add(i,T,-du[i]/2),add(T,i,0);
}
if(dinic()==maxflow) return true;
return false;
}
int h[2005],cnt;
void addedge(int x,int y,int z)
{
E[++cnt].to=y; E[cnt].nxt=h[x]; E[cnt].v=z; h[x]=cnt;
}
int visit[2005],p[maxn],gs;
void Dfs(int u)
{
for(int i=h[u];i;i=E[i].nxt)
{
// h[u]=i;
if(visit[E[i].v]) continue;
visit[E[i].v]=1;
Dfs(E[i].to);
p[++gs]=E[i].v;
}
}
void print(int ans)
{
check(ans);
for(int i=1;i<=m;i++)
{
if(val1[i]<=ans && val2[i]<=ans)
{
if(e[id[i]].v==0) addedge(v[i],u[i],i);
else addedge(u[i],v[i],i);
continue;
}
else if(val1[i]<=ans) addedge(u[i],v[i],i);
else if(val2[i]<=ans) addedge(v[i],u[i],i);
}
Dfs(1);
for(int i=gs;i>=1;i--) printf("%d ",p[i]);
printf("\n");
}
int main()
{
// freopen("euler.in","r",stdin);
// freopen("euler.out","w",stdout);
scanf("%d%d",&n,&m);
int l=inf,r=0,ans=-1;
block=n;
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&u[i],&v[i],&val1[i],&val2[i]);
int fu=find(u[i]),fv=find(v[i]);
if(fu!=fv)
{
block--;
fa[fu]=fv;
}
vis[u[i]]=vis[v[i]]=1;
if(val1[i]>val2[i])
{
swap(val1[i],val2[i]);
swap(u[i],v[i]);
}
l=min(l,val1[i]); r=max(r,val2[i]);
}
int single=0;
for(int i=1;i<=n;i++) if(!vis[i]) single++;
if(block>1 && block-single!=1)
{
printf("NIE");
return 0;
}
while(l<=r)
{
int mid=l+r>>1;
if(check(mid))
{
ans=mid;
r=mid-1;
}
else l=mid+1;
}
if(ans==-1)
{
printf("NIE");
return 0;
}
printf("%d\n",ans);
print(ans);
return 0;
}