zoukankan      html  css  js  c++  java
  • luogu P3225 [HNOI2012]矿场搭建

    传送门

    刷这个题之前就觉得自己点双不太会QAQ

    最后果然是点双写跪了……

    题意与连通性有关+无向图 考虑tarjan->割点

    自动想到分情况

    对于每一个点双进行考虑

    只有一个点肯定要放 方案数1

    同理 如果一个割点都没有 需要放两个出口防止其中一个塌了 方案数C(sze,2)

    如果只有有一个割点 那么一定要在里面放一个而且除了割点随便放(防止割点塌)方案数sze-1

    如果有两个以上割点 那么一个都不用放 因为一个割点塌另一个也可以用

    注意:

    1.tot初值设为1……

    2.我万年不用vector这次都用了(存点双所有点真恶心…)

    3.tarjan点双弹栈谈到儿子(Debug的时候样例直接出一个sze=50000…)

    Code:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<cmath>
      5 #include<queue>
      6 #include<vector>
      7 #define ms(a,b) memset(a,b,sizeof a)
      8 #define rep(i,a,n) for(int i = a;i <= n;i++)
      9 #define per(i,n,a) for(int i = n;i >= a;i--)
     10 #define inf 2147483647
     11 using namespace std;
     12 typedef long long ll;
     13 ll read() {
     14     ll as = 0,fu = 1;
     15     char c = getchar();
     16     while(c < '0' || c > '9') {
     17         if(c == '-') fu = -1;
     18         c = getchar();
     19     }
     20     while(c >= '0' && c <= '9') {
     21         as = as * 10 + c - '0';
     22         c = getchar();
     23     }
     24     return as * fu;
     25 }
     26 const int N = 505;
     27 //head
     28 int n,m,T;
     29 int head[N],nxt[N<<1],mo[N<<1],cnt;
     30 void _add(int x,int y) {
     31     mo[++cnt] = y;
     32     nxt[cnt] = head[x];
     33     head[x] = cnt;
     34 }
     35 void add(int x,int y){if(x^y)_add(x,y),_add(y,x);}
     36 
     37 int dfn[N],low[N],stk[N],top,idx,scc;
     38 bool cut[N];
     39 
     40 vector<int> mem[N];
     41 
     42 void tarjan(int x,bool rt) {
     43     dfn[x] = low[x] = ++idx;
     44     stk[++top] = x;
     45     int cld = 0;
     46     for(int i = head[x];i;i = nxt[i]) {
     47     int sn = mo[i];
     48     if(!dfn[sn]) {
     49         tarjan(sn,0);
     50         low[x] = min(low[x],low[sn]);
     51         if(low[sn] == dfn[x]) {
     52         mem[++scc].push_back(x);
     53         int t = -1;
     54         while(t != sn) {
     55             t = stk[top--];
     56             mem[scc].push_back(t);
     57         }
     58         cld++;
     59         cut[x] = 1;
     60         }
     61     } else low[x] = min(low[x],dfn[sn]);
     62     }
     63     if(rt && cld < 2) cut[rt] = 0;
     64 }
     65 
     66 
     67 void clr() {
     68     rep(i,1,scc) mem[i].clear();
     69     ms(low,0),ms(dfn,0),ms(head,0),ms(cut,0);
     70     cnt = top = scc = idx = n = m = 0;
     71 }
     72 
     73 ll C2(ll n) {return n*(n-1)/2;}
     74 
     75 void solve() {
     76     clr();
     77     m = read();
     78     if(!m) exit(0);
     79     rep(i,1,m) {
     80     int x = read();
     81     int y = read();
     82     n = max(n,max(x,y));
     83     add(x,y);
     84     }
     85     int ans = 0;
     86     ll tot = 1;
     87     rep(i,1,n) if(!dfn[i]) top = 0,tarjan(i,1);
     88     rep(i,1,scc) {
     89     int num = 0;
     90     ll sze = (ll)mem[i].size();
     91     rep(j,0,sze-1) if(cut[mem[i][j]]) num++;
     92     if(sze == 1ll) ans++;
     93     else if(!num) ans += 2,tot *= C2(sze);
     94     else if(num == 1) ans++,tot *= sze - 1;
     95     }
     96     printf("Case %d: %d %lld
    ",++T,ans,tot);
     97 }
     98     
     99 
    100 int main() {
    101     while(1) solve();
    102 }
    > 别忘了 总有人在等着你
  • 相关阅读:
    《CMake实践》笔记二:INSTALL/CMAKE_INSTALL_PREFIX
    《CMake实践》笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE
    《CMake实践》第三部分的示例代码的错误
    利用 autoconf 和 automake 生成 Makefile 文件
    如何安装 罗技“优联技术”无线鼠标、无线键盘?
    make 和 makefile 的关系
    编译器 cc、gcc、g++、CC 的区别
    如何撤销 PhpStorm/Clion 等 JetBrains 产品的 “Mark as Plain Text” 操作 ?
    Linux/Ubuntu tree 命令以树形结构显示文件夹目录结构
    C/C++ 静态链接库(.a) 与 动态链接库(.so)
  • 原文地址:https://www.cnblogs.com/yuyanjiaB/p/9756331.html
Copyright © 2011-2022 走看看