版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/IDrandom/article/details/89409764
A.pylons
小数据暴力,大数据根据ore定理用延长通路法构造解,这里参考了
https://www.cnblogs.com/zhj5chengfeng/p/3233992.html
这篇blog的总结,赛内我犯了sb错误,把下标当数用了当场GG,然后,然后就没了
#include<bits/stdc++.h>
using namespace std;
struct edge{
int v,nxt;
}e[200000];
int h[405];
int vis[405];
int deg[405];
stack<int>ans;
int cnt=0;
void init(){
memset(e,-1,sizeof e);
memset(h,-1,sizeof h);
memset(vis,0,sizeof vis);
memset(deg,0,sizeof deg);
while(!ans.empty())ans.pop();
cnt=0;
}
void add(int u,int v){
e[cnt].v=v;
e[cnt].nxt=h[u];
h[u]=cnt++;
}
struct Hamilton_Circuit {
static const int N=405;
bool G[N][N], vs[N];
int n, next[N], head, tail;
void init(int _n) {
n=_n;
memset(G, 0, sizeof G);
for(int i=0;i<_n;i++){
for(int j=h[i];~j;j=e[j].nxt){
G[i][e[j].v]=1;
}
}
}
void DFS_Head(int u) {
vs[u]=1;
for(int i=0; i<n; i++) if(G[i][u] && !vs[i]) {
next[i]=u;
DFS_Head(i);
return;
}
head=u;
}
void DFS_Tail(int u) {
vs[u]=1;
for(int i=0; i<n; i++) if(G[u][i] && !vs[i]) {
next[u]=i;
DFS_Tail(i);
return;
}
tail=u;
}
void Reverse(int u) {
for(int i=next[u], temp, last=-1; i!=-1; i=temp) {
temp=next[i];
next[i]=last;
last=i;
}
int temp=tail;
tail=next[u];
next[u]=temp;
}
int Find(int u) {
for(int i=head; i!=-1; i=next[i]) {
if(G[u][next[i]]) return i;
}
return -1;
}
bool Extend(int u) {
if(G[u][head]) {
next[u]=head;
return 1;
}
int pre=Find(u);
if(pre==-1) return 0;
next[u]=next[pre];
next[tail]=head;
next[tail=pre]=-1;
return 1;
}
void Solve() {
memset(next, -1, sizeof next);
memset(vs, 0, sizeof vs);
DFS_Head(0), DFS_Tail(0);
int Len=1;
for(int i=head; i!=tail; i=next[i], Len++);
for(int i; 1; ) {
if(!G[tail][head]) {
for(i=next[head]; !(G[i][tail] && G[next[i]][head]); i=next[i]);
Reverse(i);
}
if(Len==n) break;
for(i=0; i<n; i++) if(!vs[i] && Extend(i)) {
head=i, vs[i]=1, Len++;
break;
}
}
}
void PRINT(int c) {
for(int i=head; head!=0; i=next[i]) {
next[tail]=head;
tail=head;
head=next[head];
next[tail]=-1;
}
for(int i=head; i!=-1; i=next[i]) {
printf("%d %d\n", i/c+1,(i%c)+1);
//if(next[i]==-1) printf("1 1\n");
}
}
};
Hamilton_Circuit fuck;
int dfs(int rt,int cnt,int n){
//printf("%d %d\n",rt,cnt);
if(cnt==n){
ans.push(rt);
return 1;
}
for(int i=h[rt];~i;i=e[i].nxt)
{
int v=e[i].v;
if(!vis[v]){
vis[v]=1;
if(dfs(v,cnt+1,n)){
ans.push(rt);
return 1;
}
vis[v]=0;
}
}
return 0;
}
int main(){
int t;
scanf("%d",&t);
for(int cas=1;cas<=t;cas++){
int r,c,n;
init();
scanf("%d%d",&r,&c);
n=r*c;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
int ux=i/c,uy=i%c;
int vx=j/c,vy=j%c;
if(ux==vx||uy==vy||(ux-uy)==(vx-vy)||(ux+uy)==(vx+vy))continue;
deg[i]++;deg[j]++;
add(i,j);add(j,i);
}
}
int mn=n;
for(int i=0;i<n;i++){
mn=min(mn,deg[i]);
}
printf("Case #%d: ",cas);
if(mn>=n/2){//construct
puts("POSSIBLE");
fuck.init(n);
fuck.Solve();
fuck.PRINT(c);
}else{//search
int f=0;
for(int i=0;i<n;i++){
vis[i]=1;
if(dfs(i,1,n)){
f=1;
break;
}
vis[i]=0;
}
if(!f)puts("IMPOSSIBLE");
else {puts("POSSIBLE");
while(!ans.empty()){
int qq=ans.top();
ans.pop();
printf("%d %d\n",qq/c+1,(qq%c)+1);
}
}
}
}
return 0;
}
C.Alien Rhyme
反向构造一颗字典树,对于一个节点,这层最多只能分出去一对,那么当前子树如果<4个就直接分割出去一对,dfs跑一跑就好了
#include<bits/stdc++.h>
using namespace std;
struct node{
int c[26];
int ans;
int sum;
}tree[100000];
int cnt=0;
char str[55];
void init(){
memset(tree,0,sizeof tree);
cnt=0;
}
void Insert(int rt,int p){
tree[rt].sum++;
if(p==-1)return;
int q=str[p]-'A';
if(tree[rt].c[q]){
Insert(tree[rt].c[q],p-1);
}else{
tree[rt].c[q]=++cnt;
Insert(cnt,p-1);
}
}
void solve(int rt){
if(rt&&tree[rt].sum<=3){
tree[rt].ans=tree[rt].sum/2;
return ;
}
for(int i=0;i<26;i++){
int son=tree[rt].c[i];
if(!son)continue;
solve(son);
tree[rt].ans+=tree[son].ans;
}
int lft=tree[rt].sum-(tree[rt].ans<<1);
if(rt&&lft>=2){
tree[rt].ans++;
}
}
int main(){
int t;
scanf("%d",&t);
for(int cas=1;cas<=t;cas++){
int n;
init();
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",str);
Insert(0,strlen(str)-1);
}
solve(0);
printf("Case #%d: %d\n",cas,tree[0].ans*2);
}
return 0;
}