例題
雜事:datamaker
感覺仙人掌好難造,我是在樹上隨機加邊
#include<bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define rvc(i,S) for(register int i = 0 ; i < (int)S.size() ; i++)
#define rvcd(i,S) for(register int i = ((int)S.size()) - 1 ; i >= 0 ; i--)
#define fore(i,x)for (register int i = head[x] ; i ; i = e[i].next)
#define forup(i,l,r) for (register int i = l ; i <= r ; i += lowbit(i))
#define fordown(i,id) for (register int i = id ; i ; i -= lowbit(i))
#define pb push_back
#define prev prev_
#define stack stack_
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-(x)))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pr;
const ld inf = 2e18;
const int N = 3e6 + 10;
const int maxn = 100020;
const ll mod = 1e9 + 7;
inline ll power(ll x,ll y){
y = ((y % (mod - 1)) + (mod - 1)) % (mod - 1);
// if ( y < 0 ) return power(power(x,-y),mod - 2);
ll res = 1;
while ( y ){
if ( y & 1 ) res = res * x % mod;
x = x * x % mod;
y >>= 1;
}
return res;
}
set <pr> s;
vector <int> e[maxn];
int fa[maxn],dth[maxn],tag[maxn];
void adde(int x,int y){
e[x].pb(y);
e[y].pb(x);
}
void dfs(int x){
rvc(i,e[x]){
int to = e[x][i];
if ( to == fa[x] ) continue;
fa[to] = x , dth[to] = dth[x] + 1;
dfs(to);
}
}
bool lca(int x,int y){
int flag = 0;
while ( x != y ){
if ( dth[x] < dth[y] ) swap(x,y);
flag |= tag[x] , x = fa[x];
}
flag |= tag[x];
return flag ^ 1;
}
void cov(int x,int y){
while ( x != y ){
if ( dth[x] < dth[y] ) swap(x,y);
tag[x] = 1 , x = fa[x];
}
tag[x] = 1;
}
int main(){
freopen("1.cnt","r",stdin);
int cnt;
scanf("%d",&cnt);
fclose(stdin);
freopen("1.cnt","w",stdout);
cout<<++cnt;
fclose(stdout);
srand(cnt + time(0));
freopen("input.txt","w",stdout);
int n = 20,m = n + rand() % 2;
cout<<n<<" "<<m<<endl;
rep(i,1,n) cout<<rand() % 100 + 1<<" ";
cout<<endl;
rep(i,2,n){
int x = rand() % (i - 1) + 1;
adde(i,x);
cout<<i<<" "<<x<<endl;
s.insert(mp(x,i)) , s.insert(mp(i,x));
}
dfs(1);
rep(i,1,m - n + 1){
int x = rand() % n + 1 , y = rand() % n + 1;
while ( x == y || !lca(x,y) || s.find(mp(x,y)) != s.end() ) x = rand() % n + 1 , y = rand() % n + 1;
cov(x,y) , s.insert(mp(x,y)) , s.insert(mp(y,x));
cout<<x<<" "<<y<<endl;
}
}
1. 求仙人掌最大權獨立集
一道40min就應該ok的圓方樹DP。
犯了兩個SB錯誤!
1. 特判方點忘了往下繼續dfs
2. 往下dfs但是環上DP用的數組標號,數組被下面的點修改
都是非常簡單。但我經常犯的錯誤!
從訓練到下來總共調了1小時20分鐘,非常浪費時間!
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define rep(i,l,r) for (int i = l ; i <= r ; i++)
const int maxn = 3e5 + 20;
const int inf = 1e9;
vector <int> e[maxn],e2[maxn];
vector <int> cur;
int tops,n,m,dfn[maxn],low[maxn],tot,tag[maxn],val[maxn],dfstime,st[maxn];
int f[maxn][2],h[maxn][2][2],g[2][2];
void adde(int x,int y){
e[x].pb(y);
e[y].pb(x);
}
void adde2(int x,int y);
void tarjian(int x,int fa){
dfn[x] = low[x] = ++dfstime;
for (int i = 0 ; i < e[x].size() ; i++){
int to = e[x][i];
if ( to == fa ) continue;
if ( !dfn[to] ){
st[++tops] = to;
tarjian(to,x);
low[x] = min(low[to],low[x]);
if ( low[to] >= dfn[x] ){
cur.clear();
do{
cur.pb(st[tops]);
}while ( st[tops--] != to );
if ( cur.size() == 1 ){
adde2(x,cur[0]);
}
else if ( cur.size() > 1 ){
tag[++tot] = 1;
adde2(x,tot);
for (int i = 0 ; i < cur.size() ; i++) adde2(tot,cur[i]);
//for (int i = 0 ; i < cur.size() ; i++) cout<<cur[i]<<" ";
// cout<<"end circle\n";
}
}
}
else{
low[x] = min(dfn[to],low[x]);
}
}
}
#define e e2
void adde2(int x,int y){
// cout<<x<<" "<<y<<endl;
e[x].pb(y);
e[y].pb(x);
}
void build(){
tot = n;
for (int i = 1 ; i <= n ; i++) if ( !dfn[i] ) tarjian(i,0);
//for (int i = 1 ; i <= n ; i++) cout<<dfn[i]<<" "<<low[i]<<endl;
}
void dfs(int x,int fa){
if ( !tag[x] ){
f[x][0] = 0 , f[x][1] = val[x];
for (int i = 0 ; i < e[x].size() ; i++){
int to = e[x][i];
if ( to == fa ) continue;
dfs(to,x);
if ( !tag[to] ){
int w = max(f[to][1],f[to][0]);
//g[x][0] = f[x][0] , g[x][1] = f[x][1] , f[x][0] = f[x][1] = 0;
f[x][0] += w;
f[x][1] += f[to][0];
}
else{
f[x][0] += f[to][0];
f[x][1] += f[to][1] - val[x];
}
}
return;
}
h[x][0][1] = h[x][1][0] = -inf , h[x][0][0] = 0 , h[x][1][1] = val[e[x][0]];
for (int i = 1 ; i < e[x].size() ; i++){
int to = e[x][i];
dfs(to,x); //忘了往下遞歸!
memcpy(g,h[x],sizeof(h[x])); //一定要注意遞歸下去的數組會改變。不能用標號h[i - 1]!!!
h[x][1][1] = g[1][0] + f[to][1];
h[x][1][0] = max(g[1][0],g[1][1]) + f[to][0];
h[x][0][1] = g[0][0] + f[to][1];
h[x][0][0] = max(g[0][0],g[0][1]) + f[to][0];
}
f[x][0] = max(h[x][0][1],h[x][0][0]);
f[x][1] = h[x][1][0];
}
#undef e
int main(){
// freopen("input.txt","r",stdin);
scanf("%d %d",&n,&m);
for (int i = 1 ; i <= n ; i++) scanf("%d",&val[i]);
for (int i = 1 ; i <= m ; i++){
int x,y;
scanf("%d %d",&x,&y);
adde(x,y);
}
build();
dfs(1,0);
// for (int i = 1; i <= tot ; i++) cout<<i<<" "<<f[i][0]<<" "<<f[i][1]<<endl;
cout<<max(f[1][0],f[1][1])<<endl;
}