提出 #36576932
ソースコード 拡げる
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<(int)n;i++)
#define per(i,a,n) for (int i=n;i-->(int)a;)
int read(){int r;scanf("%d",&r);return r;}
class TwoSat{
vector<int> low; // 能达到的最小的点
vector<int> dfn; // tarjan 用的深搜访问次序标识
stack<int> stk; // tarjan 用的stk
vector<int> res; // tarjan 结果
vector<vector<int> > p; // 所有点
int n;
void scc(int v) {
static int id = 0;
low[v] = dfn[v] = id++;
stk.push(v);
for(auto w:p[v]){
if(dfn[w] == -1){ // 未访问过
scc(w);
low[v] = min(low[v],low[w]);
} else if(res[w] == -1){ // 访问过但没有结果(在栈中)
low[v] = min(low[v],dfn[w]);
}
}
int u;
if(low[v] == dfn[v]) {
do{
res[u = stk.top()] = v;
stk.pop();
}while(u != v);
}
}
vector<vector<int> > sccgroup(){
rep(i,0,2*n) if(res[i]==-1) scc(i);
vector<pair<int,int> > gi;
rep(i,0,2*n) gi.push_back({res[i],i});
sort(gi.begin(),gi.end());
vector<vector<int> > group;
rep(i,0,2*n){
if(i==0||gi[i].first != gi[i-1].first) group.push_back({gi[i].second}); // new group
else group.back().push_back(gi[i].second); // same group
}
return group;
}
public:
TwoSat(int SZ):n(SZ){ // 点范围[0..SZ-1]
low = vector<int>(2*n,-1);
dfn = vector<int>(2*n,-1);
stk = {};
res = vector<int> (2*n,-1);
p = vector<vector<int> >(2*n);
}
bool calc(vector<bool> & ans){
auto group=sccgroup();
vector<int> i2g(2*n);
rep(i,0,group.size()) for(auto idx:group[i]) i2g[idx]=i;
rep(i,0,n) if(i2g[i*2]==i2g[i*2+1])return false; // 同一个块的真假都在一个scc里
vector<int> sccmutex(group.size()); // 互斥scc
rep(i,0,n) { // 每个点的true/false 状态互斥,唯一, 因为建立边时的对称逻辑边
sccmutex[i2g[i*2]] = i2g[i*2+1];
sccmutex[i2g[i*2+1]] = i2g[i*2];
}
vector<vector<int> > G(group.size()); // 图
vector<int> degree(group.size(),0);
// 跨scc的反向边, 做拓扑选择, (因为scc计算后,剩下的一定是偏序不会有环)
rep(i,0,2*n) for(auto j:p[i]) if(i2g[i]!=i2g[j]) G[i2g[j]].push_back(i2g[i]); // i -> j 反向边
for(auto &s:G){// 去重
sort(begin(s),end(s));
s.resize(unique(begin(s),end(s))-begin(s));
}
for(auto &s:G) for(auto t:s) degree[t]++;
vector<int> d0; // 入度为0
rep(v,0,degree.size()) if(!degree[v]) d0.push_back(v);
vector<int> sccpick(group.size(), -1); // scc -1未选, true选/false不选
rep(i,0,d0.size()) {
if(sccpick[d0[i]] == -1){ // 没有计算过
// prinpick("pick %d, unpick %d\n",d0[i],sccmutex[d0[i]]);
sccpick[d0[i]] = true;
sccpick[sccmutex[d0[i]]] = false;
}
for(auto item:G[d0[i]]) if(!(--degree[item])) d0.push_back(item); // 更新入度排序
}
ans = vector<bool>(n);
rep(i,0,n) ans[i] = sccpick[i2g[i*2+1]];
return true;
}
void then(pair<int,bool> pi, pair<int,bool> pj){ // {i,true/false} -> {j,true/false}
auto [i,bi] = pi;
auto [j,bj] = pj;
assert(i >= 0 && i < n);
assert(j >= 0 && j < n);
p[2*i+bi].push_back(2*j+bj);
if(2*i+bi!=2*j+(!bj)) p[2*j+(!bj)].push_back(2*i+(!bi)); // 自动建立逻辑边
}
};
// ---------------- lib ----------------
int main(){
int n = read();
int m = read(); // xi \in [0,m]
int q = read();
TwoSat ts(n*(m+1));
auto _=[&](int i,int v){return i*(m+1)+v;}; // 编码 a[i] (>=v false, < v true)
auto ge=[&](int i,int v){return pair<int,bool>{_(i,v),false};}; // greater equal than
auto lt=[&](int i,int v){return pair<int,bool>{_(i,v),true};}; // less than
auto chk=[&](int v){return 0<=v && v<=m;};
rep(i,0,n) rep(v,1,m+1) ts.then(ge(i,v),ge(i,v-1)); // a[i]>=x 则 a[i] >= x-1 小于自动对称逻辑边
// 不能 < 0, 所以建立 < 0 则 >= 0
rep(i,0,n) ts.then(lt(i,0),ge(i,0));
while(q--){
int i=read()-1;
int j=read()-1;
int mn = read();
int mx = read();
// a[i]+a[j] >= x = mn, a[i] < v 则 a[j] >= x-v+1
rep(v,0,m+1) if(chk(mn-v+1)) ts.then(lt(i,v),ge(j,mn-v+1)); // j到i 自动对称
if(chk(mn-m)){ // mn-v+1 < 0的话 就是全部都可以 不需要建立失败逻辑, 而 a[j] >= x-v+1 > m 才需要
int v=mn-m;
ts.then(lt(i,v),ge(i,v));
ts.then(lt(j,v),ge(j,v));
}
// a[i]+a[j] <= x = mx, a[i] >= v 则 aj < x-v+1
rep(v,1,m+1) if(chk(mx-v+1)) ts.then(ge(i,v),lt(j,mx-v+1)); // j到i 自动对称
if(chk(mx+1)){ // 同理 建立失败逻辑
int v=mx+1;
ts.then(ge(i,v),lt(i,v));
ts.then(ge(j,v),lt(j,v));
}
}
vector<bool> res= {};
bool ok = ts.calc(res); // scc 联通分量 标识
if(!ok){
printf("-1\n");
return 0;
}
rep(i,0,n) per(v,0,m+1) if(!res[_(i,v)]){ // a[i] >= v
printf("%d ",v);// ans[i] = v;
break;
}
return 0;
}
提出情報
コンパイルエラー
./Main.cpp: In function ‘int read()’:
./Main.cpp:5:23: warning: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result]
5 | int read(){int r;scanf("%d",&r);return r;}
| ~~~~~^~~~~~~~~
ジャッジ結果
セット名 |
Sample |
All |
得点 / 配点 |
0 / 0 |
600 / 600 |
結果 |
|
|
セット名 |
テストケース |
Sample |
example0.txt, example1.txt |
All |
example0.txt, example1.txt, handmade0.txt, handmade1.txt, random0.txt, random1.txt, random10.txt, random11.txt, random12.txt, random13.txt, random14.txt, random15.txt, random16.txt, random17.txt, random18.txt, random19.txt, random2.txt, random20.txt, random21.txt, random22.txt, random23.txt, random24.txt, random25.txt, random26.txt, random27.txt, random28.txt, random29.txt, random3.txt, random30.txt, random31.txt, random32.txt, random33.txt, random34.txt, random35.txt, random4.txt, random5.txt, random6.txt, random7.txt, random8.txt, random9.txt |
ケース名 |
結果 |
実行時間 |
メモリ |
example0.txt |
AC |
5 ms |
3748 KiB |
example1.txt |
AC |
2 ms |
3688 KiB |
handmade0.txt |
AC |
2 ms |
3784 KiB |
handmade1.txt |
AC |
2 ms |
3764 KiB |
random0.txt |
AC |
1013 ms |
302324 KiB |
random1.txt |
AC |
1051 ms |
330148 KiB |
random10.txt |
AC |
913 ms |
349824 KiB |
random11.txt |
AC |
796 ms |
194900 KiB |
random12.txt |
AC |
1315 ms |
378288 KiB |
random13.txt |
AC |
1422 ms |
397348 KiB |
random14.txt |
AC |
492 ms |
211188 KiB |
random15.txt |
AC |
489 ms |
215524 KiB |
random16.txt |
AC |
924 ms |
357168 KiB |
random17.txt |
AC |
653 ms |
183500 KiB |
random18.txt |
AC |
1412 ms |
381300 KiB |
random19.txt |
AC |
1488 ms |
388884 KiB |
random2.txt |
AC |
484 ms |
212224 KiB |
random20.txt |
AC |
492 ms |
229128 KiB |
random21.txt |
AC |
470 ms |
216160 KiB |
random22.txt |
AC |
961 ms |
373372 KiB |
random23.txt |
AC |
703 ms |
215260 KiB |
random24.txt |
AC |
1183 ms |
383676 KiB |
random25.txt |
AC |
1152 ms |
392356 KiB |
random26.txt |
AC |
474 ms |
238548 KiB |
random27.txt |
AC |
500 ms |
253264 KiB |
random28.txt |
AC |
802 ms |
318480 KiB |
random29.txt |
AC |
1043 ms |
371228 KiB |
random3.txt |
AC |
462 ms |
202140 KiB |
random30.txt |
AC |
1052 ms |
317344 KiB |
random31.txt |
AC |
1073 ms |
326912 KiB |
random32.txt |
AC |
503 ms |
206080 KiB |
random33.txt |
AC |
506 ms |
208332 KiB |
random34.txt |
AC |
860 ms |
329544 KiB |
random35.txt |
AC |
816 ms |
217152 KiB |
random4.txt |
AC |
828 ms |
326460 KiB |
random5.txt |
AC |
734 ms |
190780 KiB |
random6.txt |
AC |
1115 ms |
338792 KiB |
random7.txt |
AC |
1157 ms |
347116 KiB |
random8.txt |
AC |
503 ms |
221488 KiB |
random9.txt |
AC |
517 ms |
232680 KiB |