hdu3861 The King’s Problem 强连通缩点+DAG最小路径覆盖

  对多校赛的题目,我深感无力。题目看不懂,英语是能懂的,题目具体的要求以及需要怎么做没有头绪。样例怎么来的都不明白。好吧,看题解吧。

  http://www.cnblogs.com/kane0526/archive/2013/07/21/3203992.html

题目大意:

  把一幅有向图中的点最少可以划分为几个区域。划分的规则是:1、可以互相到达的点必须在同一区域。2、每个城市都必须被划分。3、对于属于同一区域中的任意两点,要么满足u->v,要么满足v->u。

  第三条规则需要着重解释一下。对于测试数据1->2,1->3,因为2与3之间没有边,所以2与3必须被划为2个区域。所以答案是2。

 

做法:

  建图求强连通(Tarjan算法),然后对得到的DAG,重新建图。遍历每条边,不属于同一连通分支的点就连一条边。正向图和反向图都可以。

  最后答案就是SCC - ans。SCC 是连通分支数,ans是最大匹配数。因为这里求的最小路径覆盖。

  最小路径覆盖 =  顶点数 -  最大匹配数

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<vector>
  5 #include<queue>
  6 #include<algorithm>
  7 using namespace std;
  8 const int N =5010, M=100010,INF=0x3f3f3f3f;;
  9 struct node
 10 {
 11     int to, next;
 12 }edge[M];
 13 int head[N], low[N], dfn[N], sta[N], belg[N], num[N];
 14 bool vis[N];
 15 int scc,index,top, tot;
 16 void tarbfs(int u)
 17 {
 18     int i,j,k,v;
 19     low[u]=dfn[u]=++index;
 20     sta[top++]=u;
 21     vis[u]=1;
 22     for(i=head[u];i!=-1;i=edge[i].next)
 23     {
 24         v=edge[i].to;
 25         if(!dfn[v])
 26         {
 27             tarbfs(v);
 28             if(low[u]>low[v]) low[u]=low[v];
 29         }
 30         else if(vis[v]&&low[u]>dfn[v]) low[u]=dfn[v];
 31     }
 32     if(dfn[u]==low[u])
 33     {
 34         scc++;
 35         do
 36         {
 37             v=sta[--top];
 38             vis[v]=0;
 39             belg[v]=scc;
 40             num[scc]++;
 41         }
 42         while(v!=u) ;
 43     }
 44 }
 45 void Tarjan(int n)
 46 {
 47     memset(vis,0,sizeof(vis));
 48     memset(dfn,0,sizeof(dfn));
 49     memset(num,0,sizeof(num));
 50     memset(low,0,sizeof(low));
 51     index=scc=top=0;
 52     for(int i=1;i<=n;i++)
 53         if(!dfn[i]) tarbfs(i);
 54 }
 55 void init()
 56 {
 57     tot=0;
 58     memset(head,-1,sizeof(head));
 59 }
 60 void addedge(int i,int j)
 61 {
 62     edge[tot].to=j; edge[tot].next=head[i];head[i]=tot++;
 63 }
 64 int cx[N],cy[N],dx[N],dy[N];
 65 bool bmask[N];
 66 int nx,dis,ans;
 67 vector<int> bmap[N];
 68 bool searchpath()
 69 {
 70     queue<int> q;
 71     dis=INF;
 72     memset(dx,-1,sizeof(dx));
 73     memset(dy,-1,sizeof(dy));
 74     for(int i=1;i<=nx;i++)
 75     {
 76         if(cx[i]==-1){ q.push(i); dx[i]=0; }
 77         while(!q.empty())
 78         {
 79             int u=q.front(); q.pop();
 80             if(dx[u]>dis) break;
 81             for(int i=0;i<bmap[u].size();i++)
 82             {
 83                 int v=bmap[u][i];
 84                 if(dy[v]==-1)
 85                 {
 86                     dy[v]= dx[u] + 1;
 87                     if(cy[v]==-1) dis=dy[v];
 88                     else
 89                     {
 90                         dx[cy[v]]= dy[v]+1;
 91                         q.push(cy[v]);
 92                     }
 93                 }
 94             }
 95         }
 96     }
 97     return dis!=INF;
 98 }
 99 int findpath(int u)
100 {
101     for(int i=0;i<bmap[u].size();i++)
102     {
103         int v=bmap[u][i];
104         if(!bmask[v]&&dy[v]==dx[u]+1)
105         {
106             bmask[v]=1;
107             if(cy[v]!=-1&&dy[v]==dis) continue;
108             if(cy[v]==-1||findpath(cy[v]))
109             {
110                 cy[v]=u; cx[u]=v;
111                 return 1;
112             }
113         }
114     }
115     return 0;
116 }
117 void maxmatch()
118 {
119     ans=0;
120     memset(cx,-1,sizeof(cx));
121     memset(cy,-1,sizeof(cy));
122     while(searchpath())
123     {
124         memset(bmask,0,sizeof(bmask));
125         for(int i=1;i<=nx;i++)
126             if(cx[i]==-1) ans+=findpath(i);
127     }
128 }
129 int main()
130 {
131     //freopen("test.txt","r",stdin);
132     int cas,i,j,k,n,m;
133     scanf("%d",&cas);
134     while(cas--)
135     {
136         scanf("%d%d",&n,&m);
137         init();
138         while(m--)
139         {
140             scanf("%d%d",&i,&j);
141             addedge(i,j);
142         }
143         Tarjan(n);
144         for(i=1;i<=n;i++) bmap[i].clear();
145         for(i=1;i<=n;i++)
146         {
147             for(k=head[i];k!=-1;k=edge[k].next)
148             {
149                 j=edge[k].to;
150                 if(belg[i]!=belg[j]) bmap[belg[j]].push_back(belg[i]);
151             }
152         }
153         nx=scc;
154         maxmatch();
155         printf("%d\n",scc-ans);
156     }
157     return 0;
158 }
View Code

 

转载于:https://www.cnblogs.com/Potato-lover/p/3989625.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值