QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#375287 | #5208. Jumbled Trees | InfinityNS | TL | 0ms | 0kb | C++20 | 8.8kb | 2024-04-03 05:21:28 | 2024-04-03 05:21:28 |
answer
#include<bits/stdc++.h>
#define ff first
#define ss second
#define pb push_back
typedef long long ll;
using namespace std;
typedef pair<int,int> pii;
int mod=998244353;
inline int add(int x,int y){int ret=x+y;if(ret>=mod)ret-=mod;return ret;}
inline int sub(int x,int y){int ret=x-y;if(ret<0)ret+=mod;return ret;}
inline int mul(int x,int y){return ((ll)x*y)%mod;}
inline int step(int base,int pw){int ret=1;while(pw){if(pw&1)ret=mul(ret,base);base=mul(base,base);pw>>=1;}return ret;}
inline int invv(int x){return step(x,mod-2);}
const int maxn=1010;
namespace flow{
struct edge{
int u,v;
ll f,c;
int eid;
};
vector<edge>e;
const int maxn=2010;
int fpos[maxn];
vector<int>vect[maxn];
int s,t;
int n;
void real_add_edge(int u,int v,int cap,int eid){
vect[u].pb(e.size());
e.pb({u,v,0,cap,eid});
vect[v].pb(e.size());
e.pb({v,u,cap,cap,eid});
}
void rem_real_add_edge(int u,int v){
vect[u].pop_back();
e.pop_back();
vect[v].pop_back();
e.pop_back();
}
void init(){
for(int i=1;i<=n;i++)
real_add_edge(i,i+n,1,-1);
s=0;
t=2*n+1;
}
void add_edge(int u,int v,int cap,int eid){
///u+n -> v
real_add_edge(u+n,v,cap,eid);
}
ll send_flow(int x,ll flow){
if(x==t)return flow;
fpos[x]=1;
for(int i=0;i<vect[x].size();i++){
int id=vect[x][i];
if(e[id].c>e[id].f && fpos[e[id].v]==0){
ll temp_flow=send_flow(e[id].v,min(flow,e[id].c-e[id].f));
if(temp_flow){
e[id].f+=temp_flow;
e[id^1].f-=temp_flow;
return temp_flow;
}
}
}
return 0;
}
vector<int> get_flow(int s1,int s2,int t1,int t2){
for(int i=0;i<e.size();i+=2){
e[i].f=0;
e[i^1].f=e[i^1].c;
}
real_add_edge(s,s1,1,-1);
real_add_edge(s,s2,1,-1);
real_add_edge(t1+n,t,1,-1);
real_add_edge(t2+n,t,1,-1);
///printf("%d %d | %d %d FIND\n",s1,s2,t1,t2);
for(int i=0;i<2;i++){
//printf("%d flow\n",i);
memset(fpos,0,sizeof(fpos));
send_flow(s,1);
//printf("%d flow\n",i);
///assert(send_flow(s,1)==1);
}
rem_real_add_edge(s,s1);
rem_real_add_edge(s,s2);
rem_real_add_edge(t1+n,t);
rem_real_add_edge(t2+n,t);
vector<int>ret;
for(int i=0;i<e.size();i++){
int a=e[i].u;
int b=e[i].v;
int f=e[i].f;
if(a>n && a<t && b<=n && b>=1 && f && e[i].eid!=-1){
ret.pb(e[i].eid);
///printf("%d %d %d %d dodao\n",a,b,n,ret.back());
}
}
///printf(" EDGES\n");
return ret;
}
}
struct edge{
int a,b,w;
};
vector<edge>e;
vector<int>vect[maxn];
vector<pii>scand;
void add_edge(int a,int b,int w){
vect[a].pb(e.size());
vect[b].pb(e.size());
e.pb({a,b,w});
flow::add_edge(a,b,1,e.size()-1);
flow::add_edge(b,a,1,e.size()-1);
}
int disc[maxn],mint[maxn],ctm;
int get_nxt(int eid,int x){
if(e[eid].a==x)return e[eid].b;
return e[eid].a;
}
int ecol[maxn],ncnt;
int compsum[maxn];
int pos[maxn];
int s;
int n,m;
void obradi(vector<int>edges){
memset(pos,0,sizeof(pos));
ncnt++;
for(int i=0;i<edges.size();i++){
int id=edges[i];
//printf("%d ",id);
pos[e[id].a]=1;
pos[e[id].b]=1;
ecol[id]=ncnt;
compsum[ncnt]=add(compsum[ncnt],e[id].w);
}
//printf(" OB\n");
int sz=-1;
for(int i=1;i<=n;i++){
sz+=pos[i];
}
scand.pb({compsum[ncnt],sz});
}
void find_bridges(int x,int p,vector<int>&stek){
disc[x]=++ctm;
mint[x]=disc[x];
///printf("%d %d XX\n",x,disc[x]);
for(int i=0;i<vect[x].size();i++){
int id=vect[x][i];
if(id==p)continue;
int nxt=get_nxt(vect[x][i],x);
if(disc[nxt]<disc[x])stek.pb(id);
if(disc[nxt])mint[x]=min(mint[x],disc[nxt]);
else{
find_bridges(nxt,id,stek);
mint[x]=min(mint[x],mint[nxt]);
if(mint[nxt]>=disc[x]){
/*printf("%d %d %d EDGE\n",x,nxt,id);
for(int i=0;i<stek.size();i++)printf("%d ",stek[i]);
printf(" STEK\n");*/
vector<int>edges;
while(stek.back()!=id){
///printf("%d sz\n",stek.size());
edges.pb(stek.back());
stek.pop_back();
}
edges.pb(stek.back());
stek.pop_back();
obradi(edges);
}
}
//printf("%d %d | %d %d AAA\n",x,e[id].b,mint[e[id].b],disc[x]);
}
///printf("%d RET\n",x);
}
bool calc_s(){
int ep=0;
s=0;
for(int i=0;i<scand.size();i++){
int v=scand[i].ff;
int cc=scand[i].ss;
// printf("%d %d \n",v,cc);
if(cc==0){
if(v!=0)return false;
}
else{
int pom=mul(v,invv(cc));
if(ep==0){
ep=1;
s=pom;
}
else{
if(s!=pom)return false;
}
}
}
return true;
}
vector<pair<int,vector<int>>>ops;
void apply_mst(int v,vector<int>o){
//assert(o.size()==n-1);
if(o.size()!=-1)while(1){}
ops.pb({v,o});
for(int i=0;i<o.size();i++){
int id=o[i];
e[id].w=sub(e[id].w,v);
//printf("%d ",id);
}
/*printf(" | %d APPLIED\n",v);
for(int i=0;i<e.size();i++){
printf("%d ",e[i].w);
}
printf(" STATE\n");*/
}
void dfs(int x,int p,vector<int>&es){
pos[x]=1;
///printf("%d dOSO\n",x);
for(int i=0;i<vect[x].size();i++){
int id=get_nxt(vect[x][i],x);
if(pos[id])continue;
es.pb(vect[x][i]);
dfs(id,vect[x][i],es);
}
}
void apply_rand_mst(){
vector<int>edges;
memset(pos,0,sizeof(pos));
dfs(1,-1,edges);
apply_mst(s,edges);
}
void solve_comp(int c){
vector<int>cand;
for(int i=0;i<e.size();i++){
if(ecol[i]==c)cand.pb(i);
}
while(cand.size()){
int id=cand.back();
cand.pop_back();
if(e[id].w==0)continue;
int id2=cand.back();
vector<int>es=flow::get_flow(e[id].a,e[id].b,e[id2].a,e[id2].b);
es.pb(id);
es.pb(id2);
/*for(int i=0;i<es.size();i++){
int id=es[i];
printf("%d %d |",e[id].a,e[id].b);
}
printf(" -> %d %d | %d %d CIKLUS\n",e[id].a,e[id].b,e[id2].a,e[id2].b);*/
memset(pos,0,sizeof(pos));
for(int j=0;j<es.size();j++){
int id=es[j];
//printf("%d AAA\n",id);
pos[e[id].b]=1;
pos[e[id].a]=1;
}
//cout<<"IDE FLOW33"<<endl;
vector<int>qry,qry2;
for(int j=0;j<es.size();j++){
int id=es[j];
dfs(e[id].a,-1,qry);
dfs(e[id].b,-1,qry);
}
//cout<<"IDE FLOW44"<<endl;
qry2=qry;
/*for(int j=0;j<qry.size();j++){
int id=qry[j];
printf("%d %d |",e[id].a,e[id].b);
}
printf(" TREE\n");*/
for(int j=0;j<es.size();j++){
int idc=es[j];
if(idc==id)qry.pb(idc);
else if(idc==id2)qry2.pb(idc);
else{
qry.pb(idc);
qry2.pb(idc);
}
}
///printf("%d %d %d SIZES\n",qry.size(),qry2.size(),es.size());
///if(qry.size()!=n-1)while(1){}
int goal=e[id].w;
apply_mst(goal,qry);
apply_mst(sub(0,goal),qry2);
}
}
int main(){
//freopen("test.txt","r",stdin);
scanf("%d %d %d",&n,&m,&mod);
flow::n=n;
flow::init();
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
add_edge(u,v,w);
}
vector<int>stek;
find_bridges(1,-1,stek);
if(!calc_s()){
printf("-1\n");
return 0;
}
///printf("%d SS\n",s);
apply_rand_mst();
for(int i=1;i<=ncnt;i++){
solve_comp(i);
}
printf("%d\n",ops.size());
for(int i=0;i<ops.size();i++){
printf("%d ",ops[i].ff);
vector<int>&pom=ops[i].ss;
for(auto x:pom)printf("%d ",x+1);
printf("\n");
}
return 0;
}
詳細信息
Test #1:
score: 0
Time Limit Exceeded
input:
3 3 101 1 2 30 2 3 40 3 1 50