2-SAT模板
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
const int MAXN = 61;
vector<int> g[MAXN] , gt[MAXN] , tree[MAXN]; // g正图 , gt 逆图 , tree缩点逆图
int n , m , cnt , ID , id[MAXN] , tree_cnt , order[MAXN] , indegree[MAXN] , color[MAXN];
bool used[MAXN] , used_tree[MAXN][MAXN];
void init()
{
for(int i=0; i < 2*n; i++) {
g[i].clear();
gt[i].clear();
}
}
void build_graph()// 建图,i << 1 与 (i << 1) + 1 相斥
{
int u , v , uu , vv ;
char c1 , c2;
for(int i=0; i < m; i++){
scanf( "%d%c %d%c" , &u , &c1 , &v , &c2 );
if(c1 == 'w'){
u = u * 2;
uu = u + 1;
}
else{
u = 2 * u + 1;
uu = u - 1;
}
if(c2 == 'w'){
v = 2 * v;
vv = v + 1;
}
else{
v = 2 * v + 1;
vv = v - 1;
}
g[u].push_back( vv );
gt[vv].push_back( u );
g[v].push_back( uu );
gt[uu].push_back( v );
}
g[0].push_back( 1 );
gt[1].push_back( 0 );
}
void dfs1( int u )
{
vector<int>::iterator v;
used[u] = true;
for(v = g[u].begin(); v != g[u].end(); v++)
if(!used[*v])
dfs1(*v);
order[cnt++] = u;
}
void dfs2( int u )
{
vector<int>::iterator v;
used[u] = true;
id[u] = ID;
for(v = gt[u].begin(); v != gt[u].end(); v++)
if(!used[*v])
dfs2(*v);
}
void scc() // 缩点
{
memset(used , 0 , sizeof(used));
cnt = 0;
for(int i=0; i < 2*n; i++)
if(!used[i])
dfs1(i);
memset(used , 0 , sizeof(used));
ID = 0;
for(int i=cnt - 1; i >= 0 ; i--)
if(!used[ order[i] ]){
ID ++;
dfs2( order[i] );
}
}
bool sat_judge() //2-sat判定
{
for(int i=0; i < 2*n; i+=2)
if(id[i] == id[i+1])
return false; //无解
return true;
}
void build_tree() //缩点成树 , 建立逆图
{
memset(used_tree , 0 , sizeof(used_tree));
memset(indegree , 0 , sizeof(indegree));
for(int i=1; i <= ID; i++) tree[i].clear();
for(int i=0; i < 2*n; i++)
for(vector<int>::iterator j=g[i].begin(); j != g[i].end(); j++)
if(!used_tree[ id[*j] ][ id[i] ] && id[*j] != id[i]) {
indegree[ id[i] ] ++;
tree[ id[*j] ].push_back( id[i] );
used_tree[ id[*j] ][ id[i] ] = true;
}
}
void topsort()//拓扑排序
{
stack<int> S;
for(int i=1; i <= ID; i++)
if(indegree[i] == 0)
S.push( i );
tree_cnt = 0;
while( !S.empty() ) {
int u = S.top();
S.pop();
order[ tree_cnt ++ ] = u; //记录反向拓扑排序的序列
vector<int>::iterator v;
for(v = tree[u].begin(); v != tree[u].end(); v++) {
indegree[*v] --;
if(indegree[*v] == 0)
S.push( *v );
}
}
}
void dfs_tree( int u )
{
vector<int>::iterator v;
color[u] = 2;
for(v = tree[u].begin(); v != tree[u].end(); v++)
if(!color[*v])
dfs_tree(*v);
}
void tree_color()//对树进行染色
{
memset(color , 0 , sizeof(color));
for(int i=0; i < tree_cnt; i++)
if(!color[ order[i] ]){
color[ order[i] ] = 1;
for(int j=0; j < 2*n; j++) {
if(id[j] == order[i]) {
int tmp ;
if(j & 1) tmp = j - 1;
else tmp = j + 1;
tmp = id[ tmp ];
if(color[tmp]) continue;
color[tmp] = 2;
dfs_tree( tmp );//对前向边染色
}
}
}
}
void answer()
{
int sign = color[ id[0] ]; //得出结果
bool flag = true;
for(int i=2; i < n*2; i++){
if(color[id[i]] == sign){
if(!flag) printf(" ");
if(i & 1) printf( "%dh" , i >> 1 );
else printf( "%dw" , i >> 1 );
flag = false;
}
}
puts("");
}
void solve()
{
build_graph();
scc();
if(!sat_judge()){ puts("bad luck"); return; }
build_tree();
topsort();
tree_color();
answer();
}
int main()
{
while(scanf("%d %d" , &n , &m ) != EOF) {
if(n == 0 && m == 0) break;
init();
solve();
}
return 0;
}
CF#80div2
A.水题。
B.水题。数列求和。
C.有一个环,找以环上的为根的树。如果不是这种情况则输出NO,注意图有可能不连通,缅怀一下再次挂掉的今神……
#include<cstdio>
#include<cstring>
using namespace std;
const int N=200;
const int inf=1<<29-1;
int dis[N][N];//用来记录最短路径
int g[N][N];//记录边的情况
int pre[N][N];//记录从i到j的最后的一个中间节点
int path[N];//记录最小环
int cnt,m,n,mmin;//最小环的顶点数
bool vis[N],cir[N];
void floyd()
{
mmin=inf;
for(int k=0;k<n;k++)
{
for(int i=0;i<k;i++)
for(int j=i+1;j<k;j++)
{
if(mmin>dis[i][j]+g[k][i]+g[k][j])
{
mmin=dis[i][j]+g[k][i]+g[k][j];
cnt=0;
int p=j;
while(p!=i) //逆向寻找前驱结点直到找到最前面的i。i->…->j
{
path[cnt++]=p;
p=pre[i][p];
}
path[cnt++]=i;
path[cnt++]=k;
}
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(dis[i][j]>dis[i][k]+dis[k][j])
{
dis[i][j]=dis[i][k]+dis[k][j];
pre[i][j]=pre[k][j];//自己好好根据注释好好理一下。
}
}
}
}
bool dfs(int s,int ss)
{
vis[s]=1;
for(int i=0;i<n;i++)if(i!=ss && g[s][i]<inf){
if(vis[i] && ss==-1) continue;
if(vis[i] || dfs(i,s)==0) return false;
}
return true;
}
int main()
{
//freopen("in","r",stdin);
//freopen("out","w",stdout);
int i,j,k,u,v;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
for(j=0;j<n;j++){
pre[i][j]=i;
g[i][j]=inf;
dis[i][j]=inf;
}
for(i=1;i<=m;i++){
scanf("%d%d",&u,&v);
g[u-1][v-1]=g[v-1][u-1]=dis[u-1][v-1]=dis[v-1][u-1]=1;
}
floyd();
if(mmin==inf){
printf("NO\n");
return 0;
}
for(i=0;i<cnt;i++) cir[path[i]]=vis[path[i]]=1;
for(i=0;i<cnt;i++)
if(dfs(path[i],-1)==0){
printf("NO\n");
return 0;
}
for(i=0;i<n;i++) if(vis[i]==0){
printf("NO\n");return 0;
}
printf("FHTAGN!\n");
return 0;
}
说毛啊今天连个模版题都没交成,心情抑郁……
还有我说codeforces你敢不敢让我把源文件加上去?不过在这种烂网速下面淡定的没掉rating充分说明我以前那个rating是有多菜,当然现在也一样…仰望hzhua大神陡增的曲线,只想说你还差的远呢…有多远呢,如果秒速5厘米,那中间可能横亘了7年以上。
明天去听梁神的网络流ORZ,期待中…所以要睡觉,真奇怪,为什么你老是要睡觉?