HDU 3639 강 연통 축 점 최적화
사고방식: 원시 적 인 사고방식 은 모든 점 에 대해 DFS 를 한 번 뛰 고 통 계 를 하 는 것 이다. 그러나 case 가 비교적 많 기 때문에 반드시 시간 을 초과 해 야 한다. 그래서 우 리 는 최적화 해 야 한다. 이 문 제 는 X 개의 점 이 자신 을 뿌리 로 하고 I, 수출 이 가장 큰 X 와 해당 하 는 I 를 포함 하 는 것 으로 바 뀔 수 있다. 그러나 이렇게 하고 싶 지 않다. 우 리 는 보통 뿌리 에서 노드 까지 이다. 이 문 제 는 노드 에서 뿌리 까지, 생각 하지 않 는 다.우 리 는 특정한 노드 를 뿌리 로 하고 가장 많이 가 진 아들 노드 의 개수 로 바 꿀 수 있다.그러나 이렇게 하면 시간 을 초과 할 수 있 습 니 다. 그러나 우 리 는 강 한 연결 로 최적화 시 키 고 강 한 연결 점 을 가 진 후에 DFS 를 뛰 는 것 을 고려 할 수 있 습 니 다. 그러나 각 조 의 데이터 가 체인 모양 이 라면 시간 을 초과 할 수 있 습 니 다. 우 리 는 주의해 야 합 니 다. 만약 에 이 노드 가 입 도 를 가지 면 반드시 최 적 화 된 것 이 아 닙 니 다. (이것 은 잘 이해 하고 스스로 생각해 보 세 요)
요약: 그림 이 있 는 문제 에 대해 최적화 가 필요 할 때 강 한 연결 점 으로 생각 할 수 있다. 예 를 들 어 이 문제 가 줄 어 들 지 않 으 면 각 점 에서 적어도 한 번 뛰 고 줄 인 후의 효율 이 큰 폭 으로 향상 된다.
code:
#include
#include
#include
#include
using namespace std;
const int maxn = 7000;
struct edge
{
int u,v,next;
}e[maxn * 10];
int n,m,tot,cntnode,num,top,cnt;
int head[maxn],dfn[maxn],low[maxn],id[maxn],st[maxn],re[maxn];
int inc[maxn];
bool ins[maxn],vis[maxn],in[maxn];
void init();
void solve(int cas);
void tarjan(int u);
void add_edge(int u,int v);
void dfs(int f,int u);
int main()
{
int T,cas = 1;
scanf("%d",&T);
while(T --){
scanf("%d%d",&n,&m);
init();
for(int i = 0;i < m;i ++){
int u,v;
scanf("%d%d",&u,&v);
add_edge(v,u);
}
solve(cas ++);
}
return 0;
}
void init()
{
for(int i = 0;i < n;i ++){
ins[i] = in[i] = false;
head[i] = dfn[i] = low[i] = -1;
inc[i] = 0;
}
tot = top = cntnode = num = 0;
}
void add_edge(int u,int v)
{
e[tot].u = u , e[tot].v = v;
e[tot].next = head[u],head[u] = tot ++;
}
void tarjan(int u)
{
low[u] = dfn[u] = num ++;
ins[u] = true;
st[++ top] = u;
for(int i = head[u];i != -1;i = e[i].next){
int v = e[i].v;
if(dfn[v] == -1){
tarjan(v);
if(low[v] < low[u])
low[u] = low[v];
}
else if(ins[v] && dfn[v] < low[u])
low[u] = dfn[v];
}
if(low[u] == dfn[u]){
int v = -1;
while(u != v){
v = st[top --];
id[v] = cntnode;
ins[v] = false;
}
cntnode ++;
}
}
void solve(int cas)
{
for(int i = 0;i < n;i ++)
if(dfn[i] == -1) tarjan(i);
// for(int i = 0;i < n;i ++)
// printf("I:%d id:%d
",i,id[i]);
for(int i = 0;i < n;i ++){
int idx = id[i];
inc[idx] ++;
}
memset(head,-1,sizeof(head));
for(int i = 0;i < m;i ++){
int u = id[e[i].u];
int v = id[e[i].v];
if(u != v)in[v] = true;
add_edge(u,v);
}
int ans = -1;
for(int i = 0;i < cntnode;i ++){
if(in[i]) continue;
cnt = 0;
for(int j = 0;j < cntnode;j ++) vis[j] = false;
dfs(i,i);
re[i] = cnt;
ans = max(ans,cnt);
}
vector rec;
for(int i = 0;i < n;i ++){
int idx = id[i];
if(in[idx]) continue;
if(re[idx] == ans)
rec.push_back(i);
}
printf("Case %d: %d
", cas ++,ans - 1);
for(int i = 0;i < rec.size();i ++)
printf("%d%c",rec[i],i == rec.size() - 1 ? '
' : ' ');
}
void dfs(int f,int u)
{
cnt += inc[u];
if(vis[u]) return ;
vis[u] = true;
for(int i = head[u];i != -1;i = e[i].next){
int v = e[i].v;
if(v == f || v == u || vis[v]) continue;
dfs(u,v);
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
HDU 1874: 원활 한 공사 계속 [Dijkstra & SPFA & Floyd]모 성 은 여러 해 동안 의 원활 한 공사 계획 을 실행 한 후에 마침내 많은 길 을 건설 하 였 다.길 을 많이 건 너 지 않 아 도 좋 지 않다. 한 도시 에서 다른 도시 로 갈 때마다 여러 가지 도로 방안 을 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.