Problem:
Problem D:
Land Mark
“Hey, what’s up? It’s already 30 minutes past eleven!”
“I’m so sorry, but actually I got lost. I have no idea where I am now at all and I got tired wandering around.
Please help!”
- Today you came to the metropolis to play with your friend. But she didn’t show up at the appointed time.
What happened to her? After some uncomfortable minutes, finally you managed to get her on line, and have
been just notified that she’s been lost in the city.
You immediately told her not to move, and asked her what are around her to figure out where she is. She told
the names of some famous land marks, in the order where she caught in her sight while she made a full turn
counterclockwise without moving around.
Fortunately, today you have a map of the city. You located all the land marks she answered on the map, but want
to know in which district of the city she’s wandering.
Write a program to calculate the area where she can be found, as soon as you can!
Input
Each input case is given in the format below:
N
x
1
y
1
...
x
N
y
N
l
1
. . .
l
N
An integer
N
in the first line specifies the number of land marks she named (
N
≤ 10). The following
N
lines
specify the x- and y-coordinates of the land marks in the city. Here you modeled the city as an unbounded two-
dimensional plane. All coordinate values are integers between 0 and 100, inclusive. The last line of a test case
specifies the order in which she found these land marks in a counterclockwise turn.
A single line containing zero indicates the end of input. This is not a part of the input and should not be processed.
Output
Your program should output one line for each test case.
The line should contain the case number followed by a single number which represents the area where she can be
found. The value should be printed with the fifth digit after the decimal point, and should not contain an absolute
error greater than 10
-5
.
If there is no possible area found under the given condition, output “No area” in a line, instead of a number. If
you cannot bound the area, output “Infinity”.
Sample Input
8
1 0
2 0
3 1
3 2
2 3
1 3
0 2
0 1
1 2 3 4 5 6 7 8
8
1 0
2 0
3 1
3 2
2 3
1 3
0 2
0 1
4 3 2 1 8 7 6 5
4
0 0
1 0
1 1
0 1
1 2 3 4
0
Output for the Sample Input
Case 1: 10.00000
Case 2: No area
Case 3: Infinity

Submitted solutions:

code_snippet: #include<iomanip>
#include<limits>
#include<thread>
#include<utility>
#include<iostream>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<numeric>
#include<cassert>
#include<random>
#include<chrono>
#include<unordered_set>
#include<unordered_map>
#include<fstream>
#include<list>
#include<functional>
#include<bitset>
#include<complex>
#include<tuple>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
typedef complex<D> P;
#define F first
#define S second
const ll E=1e18+7;
const ll MOD=1000000007;


template<typename T,typename U>istream & operator >> (istream &i,pair<T,U> &A){i>>A.F>>A.S; return i;}
template<typename T>istream & operator >> (istream &i,vector<T> &A){for(auto &I:A){i>>I;} return i;}
template<typename T,typename U>ostream & operator << (ostream &o,pair<T,U> &A){o<<A.F<<" "<<A.S; return o;}
template<typename T>ostream & operator << (ostream &o,vector<T> &A){ll i=A.size(); for(auto &I:A){o<<I<<(--i?" ":"");} return o;}
template<typename T>vector<T> & cset(vector<T> &A,T e=T()){for(auto &I:A){I=e;} return A;}

namespace Geometry{
    typedef long double D;
    typedef complex<long double> P;
    typedef pair<P,D> C;
    
    const D EPS=1e-9;
    const D PI=asin(1)*2;
    const D INF=1e18;
    
    const static bool comp(const P &p1,const P &p2){return p1.real()==p2.real()?p1.imag()<p2.imag():p1.real()<p2.real();}
    
    D dot(P p1,P p2){return p1.real()*p2.real()+p1.imag()*p2.imag();}
    
    D cross(P p1,P p2){return p1.real()*p2.imag()-p1.imag()*p2.real();}
    
    P project(P vec,P x){return vec*(x/vec).real();}
    
    P project(P p1,P p2,P x){return p1+project(p2-p1,x-p1);}
    
    P reflect(P vec,P x){return vec*conj(x/vec);}
    
    P reflect(P p1,P p2,P x){return p1+reflect(p2-p1,x-p1);}
    
    bool intersectSL(P p1,P p2,P vec){vec/=abs(vec); p1/=vec; p2/=vec; return (p1.imag()<EPS && p2.imag()>-EPS) || (p1.imag()>-EPS && p2.imag()<EPS);}
    
    bool intersectSL(P p1,P p2,P p3,P p4){return intersectSL(p1-p4,p2-p4,p3-p4);}
    
    bool intersectSS(P p1,P p2,P p3,P p4){return (dot(p2-p1,p3-p1)<-EPS && dot(p2-p1,p4-p1)<-EPS) || (dot(p1-p2,p3-p2)<-EPS && dot(p1-p2,p4-p2)<-EPS)?false:intersectSL(p1,p2,p3,p4) && intersectSL(p3,p4,p1,p2);}
    
    D distLP(P vec,P x){return abs((x/vec).imag())*abs(vec);}
    
    D distLP(P p1,P p2,P x){return distLP(p2-p1,x-p1);}
    
    D distSP(P p1,P p2,P x){return dot(p2-p1,x-p1)<-EPS?abs(x-p1):dot(p1-p2,x-p2)<-EPS?abs(x-p2):distLP(p1,p2,x);}
    
    D distSS(P p1,P p2,P p3,P p4){return intersectSS(p1,p2,p3,p4)?0.0:min(min(distSP(p1,p2,p3),distSP(p1,p2,p4)),min(distSP(p3,p4,p1),distSP(p3,p4,p2)));}
    
    P crosspointLL(P p1,P p2,P vec){return abs(cross(p2-p1,vec))<EPS?vec:vec*cross(p2-p1,p2)/cross(p2-p1,vec);}
    
    P crosspointLL(P p1,P p2,P p3,P p4){return p4+crosspointLL(p1-p4,p2-p4,p3-p4);}
    
    P crosspointSS(P p1,P p2,P p3,P p4){return distSP(p1,p2,p3)<EPS?p3:distSP(p1,p2,p4)<EPS?p4:crosspointLL(p1,p2,p3,p4);}
    
    bool intersectShL(P p1,P p2,P vec){vec/=abs(vec); return intersectSL(p1,p2,vec) && crosspointLL(p1/vec,p2/vec,vec/vec).real()>-EPS;}
    
    bool intersectShL(P p1,P p2,P p3,P p4){return intersectShL(p1-p3,p2-p3,p4-p3);}
    
    //1::in,0::on edge,-1::out
    int contain(const vector<P> &poly,const P &p){
        vector<P> A={{65537,96847},{-24061,6701},{56369,-86509},{-93763,-78049},{56957,10007}};
        vector<bool> cnt(5,false);
        for(int i=1;i<=poly.size();i++){
            if(distSP(poly[i-1],poly[i%poly.size()],p)<EPS){return 0;}
            for(int j=0;j<5;j++){
                if(intersectShL(poly[i-1],poly[i%poly.size()],p,p+A[j])){cnt[j]=!cnt[j];}
            }
        }
        int in=0;
        for(int j=0;j<5;j++){if(cnt[j]){in++;}}
        return in>=3?1:-1;
    }
    
    vector<P> convexcut(const vector<P> &poly,P p1,P p2){
        vector<P> ret;
        for(int i=1;i<=poly.size();i++){
            if(cross(p2-p1,poly[i-1]-p1)>-EPS){ret.push_back(poly[i-1]);}
            if(intersectSL(poly[i-1],poly[i%poly.size()],p1,p2) && distLP(p1,p2,poly[i-1])>EPS && distLP(p1,p2,poly[i%poly.size()])>EPS){ret.push_back(crosspointLL(poly[i-1],poly[i%poly.size()],p1,p2));}
        }
        return ret;
    }
    
    D area(const vector<P> &poly){
        D ans=0;
        for(int i=2;i<poly.size();i++){ans+=cross(poly[i-1]-poly[0],poly[i]-poly[0]);}
        return abs(ans)/2;
    }
    
    vector<P> convexhull(vector<P> pts){
        vector<P> ret;
        sort(pts.begin(),pts.end(),comp);
        for(auto &I:pts){
            if(!ret.empty() && I==ret.back()){continue;}
            while(ret.size()>=2 && cross(ret.back()-ret[ret.size()-2],I-ret.back())<-EPS){ret.pop_back();}
            ret.push_back(I);
        }
        reverse(pts.begin(),pts.end());
        for(auto &I:pts){
            if(!ret.empty() && I==ret.back()){continue;}
            while(ret.size()>=2 && cross(ret.back()-ret[ret.size()-2],I-ret.back())<-EPS){ret.pop_back();}
            ret.push_back(I);
        }
        if(ret[0]==ret.back()){ret.pop_back();}
        return ret;
    }
    
    //4::seperate,3::circumscribe,2::intersect,1::inscribe,0::contain,-1::same
    int intersectCC(C c1,C c2){
        D d=abs(c1.F-c2.F),r=c1.S+c2.S,dif=abs(c2.S-c1.S);
        if(d<EPS && dif<EPS){return -1;}
        if(d-r>EPS){return 4;}
        if(d-r>-EPS){return 3;}
        if(d-dif>EPS){return 2;}
        if(d-dif>-EPS){return 1;}
        return 0;
    }
    
    vector<P> crosspointLC(P p1,P p2,C c){
        vector<P> ret;
        P pr=project(p1,p2,c.F);
        D d=distLP(p1,p2,c.F);
        if(d-c.S>EPS){return ret;}
        if(d-c.S>-EPS){ret.push_back(pr); return ret;}
        P vec=p2-p1; vec*=sqrt(c.S*c.S-d*d)/abs(vec);
        ret.push_back(pr-vec);
        ret.push_back(pr+vec);
        return ret;
    }
    
    vector<P> crosspointSC(P p1,P p2,C c){
        vector<P> ret;
        for(auto &I:crosspointLC(p1,p2,c)){if(distSP(p1,p2,I)<EPS){ret.push_back(I);}}
        return ret;
    }
    
    vector<P> crosspointCC(C c1,C c2){
        vector<P> ret;
        P vec=c2.F-c1.F;
        D base=(c1.S*c1.S+norm(vec)-c2.S*c2.S)/(2*abs(vec));
        D h=sqrt(c1.S*c1.S-base*base);
        vec/=abs(vec);
        ret.push_back(c1.F+vec*P(base,-h));
        ret.push_back(c1.F+vec*P(base,h));
        return ret;
    }
    
    vector<P> tangentCP(C c,P p){return crosspointCC(c,C(p,sqrt(norm(c.F-p)-c.S*c.S)));}
    
    vector<pair<P,P>> tangentCC(C c1,C c2){
        vector<pair<P,P>> ret;
        P d=c2.F-c1.F;
        for(D i:{-1,1}){
            D r=c1.S+c2.S*i;
            if(intersectCC(c1,c2)>i+1){
                for(P s:{-1i,1i}){
                    P p=r+s*sqrt(norm(d)-norm(r));
                    ret.push_back({c1.F+d*c1.S/norm(d)*p,c2.F-d*i*c2.S/norm(d)*p});
                }
            }
        }
        return ret;
    }
    
    D area(const vector<P> &poly,C c){
        D ret=0;
        for(int i=0;i<poly.size();i++){
            P a=poly[i]-c.F,b=poly[(i+1)%poly.size()]-c.F;
            if(abs(a)<c.S+EPS && abs(b)<c.S+EPS){ret+=cross(a,b);}
            else{
                vector<P> A=crosspointSC(a,b,{0,c.S});
                if(A.empty()){ret+=c.S*c.S*arg(b/a);}
                else{
                    ret+=(abs(a)<c.S?cross(a,A[0]):c.S*c.S*arg(A[0]/a));
                    ret+=(abs(b)<c.S?cross(A.back(),b):c.S*c.S*arg(b/A.back()));
                    ret+=cross(A[0],A.back());
                }
            }
        }
        return abs(ret)/2;
    }
    
    //反時計回り
    D diameter(const vector<P> &poly){
        D ret=0;
        ll l=0,r=0,n=poly.size();
        if(n==2){return abs(poly[0]-poly[1]);}
        for(int i=0;i<n;i++){
            if(comp(poly[l],poly[i])){l=i;}
            if(comp(poly[i],poly[r])){r=i;}
        }
        ll sl=r,sr=l;
        while(sl!=l || sr!=r){
            ret=max(ret,abs(poly[r]-poly[l]));
            if(cross(poly[(l+1)%n]-poly[l],poly[(r+1)%n]-poly[r])<0){(++l)%=n;}
            else{(++r)%=n;}
        }
        return ret;
    }
    
    D closestpair(vector<P> pt){
        sort(pt.begin(),pt.end(),comp);
        D ret=INF;
        for(ll i=1;i<pt.size();i<<=1){
            for(ll j=0;i+j<pt.size();j+=i*2){
                ll m=i+j;
                vector<P> R;
                D l=-INF,r=INF;
                for(ll k=j;k<m;k++){l=max(l,pt[k].real());}
                for(ll k=0;m+k<pt.size() && k<i;k++){r=min(r,pt[m+k].real());}
                for(ll k=0;m+k<pt.size() && k<i;k++){if(pt[m+k].real()-l<ret){R.push_back(pt[m+k]);}}
                ll idx=0;
                for(ll k=j;k<m;k++){
                    if(r-pt[k].real()>ret){continue;}
                    while(idx<R.size() && pt[k].imag()-R[idx].imag()>ret){idx++;}
                    for(ll n=idx;n<R.size() && R[n].imag()-pt[k].imag()<ret;n++){ret=min(ret,abs(R[n]-pt[k]));}
                }
                inplace_merge(pt.begin()+j,pt.begin()+m,j+i*2<pt.size()?pt.begin()+j+2*i:pt.end(),[](const P &a,const P &b){return a.imag()==b.imag()?a.real()<b.real():a.imag()<b.imag();});
            }
        }
        return ret;
    }
    
    P centerofgravity(const vector<P> &pt){
        P ret(0,0);
        D wt=0;
        for(int i=2;i<pt.size();i++){
            D w2=cross(pt[i-1]-pt[0],pt[i]-pt[0]);
            P p=(pt[0]+pt[i-1]+pt[i])/(D)3;
            wt+=w2;
            ret+=p*w2;
        }
        return ret/wt;
    }
    
    istream & operator >> (istream &i,P &p){D x,y; i>>x>>y; p={x,y}; return i;}
    istream & operator >> (istream &i,C &p){D x,y; i>>x>>y>>p.S; p.F={x,y}; return i;}
};

using namespace Geometry;


D distPP(vector<P> &A,vector<P> &B){
    D ret=INF;
    ll n=A.size(),m=B.size();
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            ret=min(ret,distSS(A[i-1],A[i%n],B[j-1],B[j%m]));
        }
    }
    return ret;
}


D cul(vector<P> &A,vector<ll> &B,ll n,ll x){
    const D F=1e9;
    vector<P> ans={P(-F,-F),P(F,-F),P(F,F),P(-F,F)};
    for(int i=1;i<=n;i++){
        if(i==x){
            ans=convexcut(ans,A[B[i%n]],A[B[i-1]]);
        }
        else{
            ans=convexcut(ans,A[B[i-1]],A[B[i%n]]);
        }
    }
    for(auto &I:ans){
        if(abs(abs(I.real())-F)<1 || abs(abs(I.imag())-F)<1){return INF*2;}
    }
    if(!ans.empty()){
        //cout<<x<<endl<<ans<<endl;
        P m=0; for(auto &I:ans){m+=I;} m/=ans.size();
        P vec=(A[B[0]]-m)/abs(A[B[0]]-m);
        D las=0;
        for(int i=1;i<n;i++){
            D a=arg((A[B[i]]-m)/vec);
            if(a<0){a+=2*PI;}
            if(a<las-EPS){return 0;}
            las=a;
        }
    }
    return area(ans);
}


int main(){
    ll n,t=1;
    while(cin>>n,n){
        vector<P> A(n);
        cin>>A;
        vector<ll> B(n);
        cin>>B;
        for(auto &I:B){I--;}
        D ans=0;
        for(int i=0;i<=n;i++){ans+=cul(A,B,n,i);}
        cout<<"Case "<<t<<": "; t++;
        if(ans<EPS){cout<<"No area"<<endl;}
        else if(ans>INF){cout<<"Infinity"<<endl;}
        else{cout<<fixed<<setprecision(5)<<ans<<endl;}
    }
    
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3256
final_rank: 4

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
using namespace std;
const double EPS = 1e-6;
const double INF = 1e7;
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<long double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};
namespace std{
    bool operator < (const P& a, const P& b){
        return !EQ(a.X,b.X) ? a.X<b.X : a.Y+EPS<b.Y;
    }
    bool operator == (const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

long double dot(P a, P b){
    return (conj(a)*b).X;
}
long double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) < -EPS) return -1; //cw
    if(dot(b,c) < -EPS) return +2; //c-a-b
    if(abs(c)-abs(b) > EPS) return -2; //a-b-c
    return 0; //a-c-b

}

bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const L &a, const L &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}
P crosspointLL(const L &l, const L &m) {
  long double A = cross(l[1]-l[0], m[1]-m[0]);
  long double B = cross(l[1]-l[0], l[1]-m[0]);
  return m[0] + B/A *(m[1]-m[0]);
}

long double getarea(const VP &poly){
    long double ret = 0;
    for (int i=0; i<(int)poly.size(); i++){ 
        ret += cross(poly[i], poly[(i+1)%poly.size()]);
    }
    return ret*0.5;
}

VP convex_cut(const VP& p, const L& l){
    VP ret;
    int n = p.size();
    for(int i=0; i<n; i++){
        P curr = p[i];
        P next = p[(i+1)%n];
        if(ccw(l[0], l[1], curr) != -1) ret.push_back(curr);
        if(ccw(l[0], l[1], curr) *ccw(l[0], l[1], next) == -1){
            ret.push_back(crosspointLL(L(curr, next), l));
        }
    }
    return ret;
}

int main(){
    for(int dn=1; ; dn++){
        int n;
        cin >> n;
        if(n == 0) break;

        VP p(n);
        for(int i=0; i<n; i++){
            int x,y;
            cin >> x >> y;
            p[i] = P(x, y);
        }
        vector<int> ord(n);
        for(int i=0; i<n; i++){
            cin >> ord[i];
            ord[i]--;
        }
        vector<int> next(n);
        for(int i=0; i<n; i++){
            next[ord[i]] = ord[(i+1)%n];
        }

        VP sq{P(-INF, -INF), P(INF, -INF), P(INF, INF), P(-INF, INF)};
        long double ans = 0;
        for(int i=0; i<(1<<n); i++){
            VP poly = sq;
            for(int j=0; j<n; j++){
                L cut(p[ord[j]], p[ord[(j+1)%n]]);
                if((i & 1<<j) != 0) swap(cut[0], cut[1]);
                poly = convex_cut(poly, cut);
            }
            if(poly.empty()) continue;
            
            P center(0, 0);
            for(const P &p: poly){
                center += p;
            }
            center /= poly.size();
            vector<pair<long double, int> > angle(n);
            for(int i=0; i<n; i++){
                angle[i] = make_pair(arg(p[i]-center), i);
            }
            sort(angle.begin(), angle.end());
            bool ok = true;
            for(int i=0; i<n-1; i++){
                if(next[angle[i].second] != angle[(i+1)%n].second){
                    ok = false;
                    break;
                }
            }
            if(!ok) continue;
            
            bool isinf = false;
            for(const P &p: poly){
                if(EQ(abs(p.X), INF) || EQ(abs(p.Y), INF)){
                    isinf = true;
                    break;
                }
            }
            long double area = getarea(poly);
            if(area > 0){
                if(isinf){
                    ans = -1;
                    break;
                }else{
                    ans += area;
                }
            }
        }

        cout << "Case " << dn << ": ";
        if(EQ(ans, 0)){
            cout << "No area" << endl;
        }else if(ans < 0){
            cout << "Infinity" << endl;
        }else{
            cout << fixed << setprecision(5);
            cout << ans << endl;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 3324
final_rank: 6

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <functional>
#include <cassert>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define pb push_back
#define eb emplace_back
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}
struct UnionFind {
  vector<int> d;
  UnionFind(int n=0) : d(n, -1){}
  bool unite(int x, int y) {
    if ((x = root(x)) != (y = root(y))){
      if (d[y] < d[x]) swap(x, y);
      d[x] += d[y]; d[y] = x;
    }
    return x != y;
  }
  bool find(int x, int y){return root(x) == root(y);}
  int root(int x){return d[x] < 0 ? x : d[x] = root(d[x]);}
  int size(int x=-1) {return x<0 ? d.size() : -d[root(x)];}
};

namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef long double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2;	// s-t-p
		return 0;								// s-p-t
	}
	
	
	struct L : public vector<P>{	// line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			// ??§?¨????????????¨EPS???????????§??????????????????????????¨???
			return !sig(outp(p-at(0), dir())) && inp(p-at(0), dir()) > EPS && inp(p-at(1), -dir()) > -EPS;
			//return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	struct C : public P{
		C(){}
		C(const P& p, const R r):P(p), r(r){}
		R r;
		BOOL inside(const P& p)const { return less(norm(p-SELF), r*r);}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
		BOOL contains(const P &p)const {
			R sum = .0;
			REP(i, size()){
				if(S(at(i), at((i+1)%size())).online(p)) return BORDER;	// online
				sum += arg((at(i) - p) / (at((i+1)%size()) - p));
			}
			return !!sig(sum);
		}
		R area()const {
			R sum = 0;
			REP(i, size()) sum += outp(at(i), at((i+1)%size()));
			return abs(sum / 2.);
		}
		P gp()const {
			P r(.0, .0);
			REP(i, size()){
				const S &s = edge(i);
				r += (s[0]+s[1])*outp(s[0], s[1]);
			}
			return r / (6*area());
		}
		G convex_hull(bool online = false) {
			if(size() < 2) return *this;
			sort(ALL(*this));
			G r;
			r.resize((int)size()*2);
			int k=0;
			for(int i=0;i<size();r[k++]=at(i++))
				while(k>1 && ccw(r[k-2], r[k-1], at(i)) < 1-online) k--;
			int t = k;
			for(int i=(int)size()-1;i>=0;r[k++]=at(i--))
				while(k>t && ccw(r[k-2], r[k-1], at(i)) < 1-online) k--;
			r.resize(k-1);
			return r;
		}
	};

	inline P proj(const P &s, const L &t){return t[0] + proj(s-t[0], t[1]-t[0]);}
	inline P reflect(const P &s, const L &t){return (R)2.*proj(s, t) - s;}
	inline S reflect(const S &s, const L &t){return S(reflect(s[0], t), reflect(s[1], t));}
	BOOL intersect(const S &s, const S &t){
		const int p = ccw(t[0], t[1], s[0], 1) * ccw(t[0], t[1], s[1], 1);
		const int q = ccw(s[0], s[1], t[0], 1) * ccw(s[0], s[1], t[1], 1);
		return (p>0||q>0) ? FALSE : (!p||!q) ? BORDER : TRUE;
	}
	BOOL intersect(const S &s, const L &l){
		if(l.online(s[0]) || l.online(s[1])) return BORDER;
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	R dist2(const L &l, const P &p){return norm(outp(l.dir(), p - l[0])) / norm(l.dir());}
	R dist2(const S &s, const P &p){
		if(inp(p-s[0],  s.dir()) < EPS) return norm(p - s[0]);
		if(inp(p-s[1], -s.dir()) < EPS) return norm(p - s[1]);
		return dist2((const L &)s, p);
	}
	R dist2(const S &s, const L &l){
		return intersect(s, l) ? .0 : min(dist2(l, s[0]), dist2(l, s[1]));
	}
	R dist2(const S &s, const S &t){
		return intersect(s, t) ? .0 : min(min(dist2(s, t[0]), dist2(t, s[0])), 
									   	  min(dist2(s, t[1]), dist2(t, s[1])));
	}
	template <class T> R dist2(const G &g, const T& t){ // todo: ?????¨????????¨?????????????????´???
		R res = INF;
		REP(i, g.size()) res = min(res, dist2(g.edge(i), t));
		return res;
	}
	template<class S, class T> R dist(const S& s, const T& t){return sqrt(dist2(s, t));}
	inline BOOL intersect(const C &a, const C &b){
		return less((a.r-b.r)*(a.r-b.r), norm(a-b)) + less(norm(a-b), (a.r+b.r)*(a.r+b.r)) - 1;
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		return m[0] + B / A * (m[1] - m[0]);
	}
	template<class T> vector<T> merge(vector<T> s) {
		REP(i, s.size()) if (s[i][1] < s[i][0]) swap(s[i][0], s[i][1]);
		sort(ALL(s));
		REP(i, s.size())REP(j, i)if(intersect(s[i], s[j]) && !sig(outp(s[i].dir(), s[j].dir()))) {
			s[j][1] = max(s[i][1], s[j][1]);
			s.erase(s.begin() + i--);
			break;
		}
		return s;
	}
	struct Arrangement{
		struct AEdge{
			int u, v, t;
			R cost;
			AEdge(int u=0, int v=0, int t=0, R cost=0)
				:u(u), v(v), t(t), cost(cost){}
		};
		typedef vector<vector<AEdge>> AGraph;
		vector<P> p;
		AGraph g;
		Arrangement(){}
		Arrangement(vector<S> seg){
			seg = merge(seg);
			int m = seg.size();
			REP(i, m){
				REP(j, i) if(sig(outp(seg[i].dir(), seg[j].dir())) && intersect(seg[i], seg[j]))
					p.push_back(crosspoint(seg[i], seg[j]));
			}
			sort(ALL(p)); UNIQUE(p);
			int n=p.size();
			g.resize(n);
			REP(i, m){
				S &s = seg[i];
				vector<pair<R, int>> ps;
				REP(j, n) if(s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
				sort(ALL(ps));
				REP(j, (int)ps.size()-1){
					const int u=ps[j].second;
					const int v=ps[j+1].second;
					g[u].emplace_back(u, v, 0, 0);
					g[v].emplace_back(v, u, 0, 0);
				}
			}
		}
		
		int getIdx(P q){
			auto it = lower_bound(ALL(p), q);
			if(it == p.end() || *it != q) return -1;
			return it - p.begin();
		}
	};
	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
		};
		
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		UnionFind uf;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()),uf(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
			uf.unite(s, t);
		}
		vector<G> poly;
		
		void add_polygon(int s, int t, R a){
			auto e = lower_bound(ALL(g[s]), a-1e-8);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			e->l = t;
			poly[t].push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		
		void toSpanningTree(){
			vector<pair<R, pii>> e;
			REP(i, n)REP(j, i)if(!uf.find(i, j))
				e.emplace_back(abs(p[i]-p[j]), pii(i, j));
			sort(ALL(e));
			REP(ii, e.size()){
				const int i = e[ii].second.first;
				const int j = e[ii].second.second;
				if(uf.find(i, j)) continue;
				const S s(p[i], p[j]);
				if([&](){
					REP(k, n)if(i!=k&&j!=k){
						FOR(it, g[k])
						if(intersect(s, S(p[k], p[it->v])) == TRUE) return 0;
					}
					return 1;
				}()) add_edge(i, j);
			}
		}
		
		void dual(){
//			toSpanningTree();
			
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			poly.emplace_back();
			add_polygon(s, poly.size()-1, -PI*(R).5);
			REP(i, n)REP(j, g[i].size())if(!g[i][j].f){
				poly.emplace_back();
				add_polygon(i, poly.size()-1, g[i][j].a+2.*EPS);
			}
		}
	};

#undef SELF
#undef at
}

using namespace geom;

namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return norm(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}

}
int T, n, m;
R W = 12000;

int check(const P &p, const vector<P> &tar){
	vector<R> args;
	REPS(i, (int)tar.size()-1){
		R a = arg((tar[i] - p) / (tar[0] - p));
		if(a < -EPS) a += 2*PI;
		args.pb(a);
	}
	REPS(i, (int)args.size()-1) if(args[i-1] > args[i]) return 0;
	return 1;
}

int main(int argc, char *argv[]){
	ios::sync_with_stdio(false);
	for(int t=1;cin >> n, n;t++){
		vector<P> g(n);
		REP(i, n) cin >> g[i];
		vi idx(n);
		REP(i, n) cin >> idx[i];
		vector<P> g2(n);
		REP(i, n) g2[i] = g[idx[i]-1];
		g = g2;
		vector<S> s;
		vector<L> ls;
		REP(i, n)REP(j, i) ls.eb(g[i], g[j]);
		W = 1000;
		REP(i, ls.size()){
			int f = 0;
			REP(j, ls.size())if(i!=j && outp(ls[i].dir(), ls[j].dir())){
				P p = crosspoint(ls[i], ls[j]);
				W = max({W, abs(p.X), abs(p.Y)}) + 1;
			}
		}
		REP(i, n)REP(j, i){
			P dir = unit(g[j] - g[i]);
			s.eb(g[i] - dir*W*(R)5, g[i] + dir*W*(R)5);
		}
		s.eb(P(-W, -W), P(W, -W));
		s.eb(P(-W, -W), P(-W, W));
		s.eb(P(W, W), P(W, -W));
		s.eb(P(W, W), P(-W, W));
		Arrangement ar(s);
		DualGraph dg(ar.p);
		for(auto &it : ar.g) for(auto &e : it)if(e.u < e.v){
			dg.add_edge(e.u, e.v);
		}
		dg.dual();
		R ans = 0;
		int inff = 0;

		REPS(i, dg.poly.size()-1){
			R area = dg.poly[i].area();
			if(area < EPS) continue;
			if(!check(dg.poly[i].gp(), g)) continue;
			ans += area;
			R minn = 0, maxx = 0;
			for(auto &p : dg.poly[i]){
				chmin(minn, min(p.X, p.Y));
				chmax(maxx, max(p.X, p.Y));
			}
			if(maxx > W-EPS || minn < -W+EPS){
				inff = 1;
				break;
			}
		}
		printf("Case %d: ", t);
		if(ans < EPS) printf("No area\n");
		else if(inff) printf("Infinity\n");
		else printf("%.20f\n", (double)ans);
	}
	return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 1824
final_rank: 5

code_snippet: #include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <climits>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<(b)?(a=b,1):0)
#define chmin(a,b) (a>(b)?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)

#define double long double
typedef long long ll;
typedef pair<int,int> pii;
const int INF = 1e8;
const double PI = acos(-1);
const double EPS = 1e-8;
typedef complex<double> P;
namespace std {
  bool operator < (const P& a, const P& b) {
    // if (abs(a-b)<EPS) return 0;
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
  L() {}
};
ostream &operator<<(ostream &os, const L &a) {
  os << a[0] << " -> " << a[1];
  return os;
}

typedef vector<P> G;
#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
struct C {
  P p; double r;
  C(const P &p, double r) : p(p), r(r) { }
};

int ccw(P a, P b, P c) {
  b -= a; c -= a;
  if (cross(b, c) > EPS)   return +1;       // counter clockwise
  if (cross(b, c) < -EPS)   return -1;       // clockwise
  if (dot(b, c) < -EPS)     return +2;       // c--a--b on line
  if (norm(b) < norm(c)) return -2;       // a--b--c on line
  return 0;
}

bool intersectLL(const L &l, const L &m) {
  return abs(cross(l[1]-l[0], m[1]-m[0])) > EPS*10 || // non-parallel
         abs(cross(l[1]-l[0], m[0]-l[0])) < EPS;   // same line
}
bool intersectLS(const L &l, const L &s) {
  return cross(l[1]-l[0], s[0]-l[0])*       // s[0] is left of l
         cross(l[1]-l[0], s[1]-l[0]) < EPS; // s[1] is right of l
}
bool intersectLP(const L &l, const P &p) {
  return abs(cross(l[1]-p, l[0]-p)) < EPS;
}
bool intersectSS(const L &s, const L &t) {
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}
bool intersectSS2(const L &s, const L &t) { // テヲツ篠・テ」ツ?療」ツ?ヲテ」ツ??」ツつ凝」ツつ?」ツ?、テ」ツ?ッテ、ツコツ、テ・ツキツョテ」ツ?ィティツ?ε」ツ?暗」ツ?ェテ」ツ??
  REP(i, 2) {
    if (ccw(s[0], s[1], t[i]) == 0) {
      int c = ccw(s[0],s[1],t[!i]);
      if (s[0] == t[i]) {
        if (c!=-2&&c) return 0;
      } else if (s[1] == t[i]) {
        if (c!=2&&c) return 0;
      } else if (abs(c)==1) return 0;
    }
  }
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}
bool intersectSP(const L &s, const P &p) {
  return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality
}
bool intersectLH(const L &l, const L &h) {
  if (intersectLS(l,h)) return 1;
  if (!intersectLL(l,h)) return 0;
  if (abs(cross(l[1]-l[0],h[1]-h[0])) < EPS) return 1; // same line
  return (ccw(l[0],l[1],h[0]) == 1) ^ (cross(l[1]-l[0], h[1]-h[0]) > 0);
}
bool intersectHS(const L &h, const L &s) {
  if (intersectSS(h,s)) return 1;
  if (!intersectLS(h,s)) return 0;
  if (abs(cross(s[1]-s[0],h[1]-h[0])) < EPS) // same line
    return ccw(h[0],h[1],s[0]) != 2 || ccw(h[0],h[1],s[1]) != 2;
  return (ccw(s[0],s[1],h[0]) == 1) ^ (cross(s[1]-s[0], h[1]-h[0]) > 0);
}
bool intersectHH(const L &h, const L &k) {
  return intersectLH(h,k) && intersectLH(k,h);
}
bool intersectHS2(const L &h, const L &s) {
  L t(s); swap(t[0],t[1]);
  return intersectHH(h,s) && intersectHH(h,t);
}

P projection(const L &l, const P &p) {
  double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
  return l[0] + t*(l[0]-l[1]);
}
P reflection(const L &l, const P &p) {
  return p + P(2,0) * (projection(l, p) - p);
}
double distanceLP(const L &l, const P &p) {
  return abs(p - projection(l, p));
}
double distanceLL(const L &l, const L &m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m[0]);
}
double istanceLS(const L &l, const L &s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s[0]), distanceLP(l, s[1]));
}
double distanceSP(const L &s, const P &p) {
  const P r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s[0] - p), abs(s[1] - p));
}
double distanceSS(const L &s, const L &t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
             min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}
P crosspoint(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
  if (abs(A) < EPS) {
    cout << abs(A) << endl;
    cout << intersectLL(l,m) << endl;
    cout << l << " " << m << endl;
  }
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}
bool intersectLHL(const L &l, const L &m) {
  if (!intersectLL(l,m)) return 0;
  P cp = crosspoint(l,m);
  if (ccw(m[0],m[1],cp) == 2) return 0;
  return 1;
}
bool intersectHLS(const L &l, const L &s) {
  if (!intersectLS(l,s)) return 0;
  P cp = crosspoint(l,s);
  if (ccw(l[0],l[1],cp) == 2) return 0;
  return 1;
}
double area(const G& g) {
  double A = 0;
  for (int i = 0; i < g.size(); ++i) {
    A += cross(g[i], next(g, i));
  }
  return abs(A/2);
}

G convex_cut(const G& g, const L& l) {
  G Q;
  REP(i, g.size()) {
    P A = curr(g, i), B = next(g, i);
    if (ccw(l[0], l[1], A) != -1) Q.push_back(A);
    if (ccw(l[0], l[1], A)*ccw(l[0], l[1], B) == -1)
      // if (abs(cross(l[1]-l[0],B-A)) > EPS)
        Q.push_back(crosspoint(L(A, B), l));
  }
  return Q;
}
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

// テ、ツクツ?ヲツァツ佚」ツ?ェテ・ツ、ツ堙ィツァツ津・ツスツ「テ」ツ?ョテゥツ?催・ツソツ?
P centroid(const vector<P> &v) {
  double S = 0;
  P res;
  REP(i,v.size()) {
    int j = i+1;
    if (j == v.size()) j = 0;
    double tmp = cross(v[i], v[j]);
    S += tmp;
    res += (v[i] + v[j]) * tmp;
  }
  S /= 2;
  res /= 6*S;
  return res;
}

double manDistanceSP(const L &l, const P &p) {
  double res = INF;
  L xl = L(p, p + P(1,0));
  if (intersectLS(xl, l)){
    P cp = crosspoint(xl, l);
    double d = abs(p-cp);
    res = min(res, d);
  }
  L yl = L(p, p + P(0,1));
  if (intersectLS(yl, l)) {
    P cp = crosspoint(yl, l);
    double d = abs(p-cp);
    res = min(res, d);
  }
  res = min(res, abs(l[0].real()-p.real()) + abs(l[0].imag()-p.imag()));
  res = min(res, abs(l[1].real()-p.real()) + abs(l[1].imag()-p.imag()));
  return res;
}

// テァツつケ-テ・ツ?クテ・ツ、ツ堙ィツァツ津・ツスツ「テ・ツ個?・ツ青ォテゥツ鳴「テ、ツソツ?
bool convex_contain(const G &g, const P &p) { // テ・ツ債甘ヲツ卍づィツィツ暗・ツ崢榲」ツつ甘」ツつ津、ツサツョテ・ツョツ?
  REP(i,g.size())
    if (ccw(g[i], next(g, i), p) == -1) return 0;
  return 1;
}
// テ・ツ?クテ・ツ、ツ堙ィツァツ津・ツスツ「テ・ツ青古・ツ」ツォテ」ツ?ョテゥツ?催」ツ?ェテ」ツつ甘・ツ按、テ・ツョツ?
bool intersectGG(const G &g1, const G &g2) {
  if (convex_contain(g1, g2[0])) return 1;
  if (convex_contain(g2, g1[0])) return 1;
  REP(i,g1.size()) REP(j,g2.size()) {
    if (intersectSS(L(g1[i], next(g1, i)), L(g2[j], next(g2, j)))) return 1;
  }
  return 0;
}
// テ・ツ?クテ・ツ、ツ堙ィツァツ津・ツスツ「テ」ツ?ィテァツつケテ」ツ?ョティツキツ敕ゥツ崢「
double distanceGP(const G &g, const P &p) {
  if (convex_contain(g, p)) return 0;
  double res = INF;
  REP(i, g.size()) {
    res = min(res, distanceSP(L(g[i], next(g, i)), p));
  }
  return res;
}
// テ・ツ楪づァツ崢エテ、ツコツ古ァツュツ嘉・ツ按?ァツキツ?
L bisector(const P &a, const P &b) {
  P A = (a+b)*P(0.5,0);
  return L(A, A+(b-a)*P(0, PI/2));
}
// テ」ツδ愿」ツδュテ」ツδ偲」ツつ、テゥツ?佚・ツ淞?
G voronoi_cell(G g, const vector<P> &v, int s) {
  REP(i, v.size())
    if (i!=s)
      g = convex_cut(g, bisector(v[s], v[i]));
  return g;
}
// ティツァツ津・ツコツヲテゥツ鳴「テゥツ?」
double angle(const P &a, const P &b) {        // テ」ツδ凖」ツつッテ」ツδ暗」ツδォテッツスツ?」ツ?凝」ツつ嘉」ツ?ソテ」ツ?淌」ツδ凖」ツつッテ」ツδ暗」ツδォテッツスツづ」ツ?ョティツァツ津・ツコツヲテ」ツ?ョティツィツ暗ァツョツ夕0,2pi)
  double ret = arg(b)-arg(a);
  return (ret>=0) ? ret : ret + 2*PI;
}
double angle2(const P &a, const P &b) { // テ」ツδ凖」ツつッテ」ツδ暗」ツδォaテ」ツ?ィテ」ツδ凖」ツつッテ」ツδ暗」ツδォbテ」ツ?ョテゥツ鳴禿」ツ?ョティツァツ津・ツコツヲ
  return min(angle(a,b), angle(b,a));
}
double rtod(double rad) {       // テ」ツδゥテ」ツつクテ」ツつ「テ」ツδウテ「ツ?津・ツコツヲ
  return rad*180/PI;
}
double dtor(double deg) {       // テ・ツコツヲテ「ツ?津」ツδゥテ」ツつクテ」ツつ「テ」ツδウ
  return deg*PI/180;
}
int quadrant(const P &a) {      // テヲツ卍づィツィツ暗・ツ崢榲」ツつ甘・ツ?エテ」ツ?ッテ・ツ青ォテ」ツ?ソテ」ツ??・ツ債甘ヲツ卍づィツィツ暗・ツ崢榲」ツつ甘・ツ?エテ」ツ?ッテ・ツ青ォテ」ツ?セテ」ツ?ェテ」ツ??
  if (a.real() > 0 && a.imag() >= 0) return 0;
  if (a.real() <= 0 && a.imag() > 0) return 1;
  if (a.real() < 0 && a.imag() <= 0) return 2;
  return 3;
}
bool cmpAngle(const P &a, const P&b) { // テ」ツδュテ」ツδ静」ツつケテ」ツδ暗」ツ?ェティツァツ津・ツコツヲテヲツッツ氾ィツシツ?
  int q1 = quadrant(a);
  int q2 = quadrant(b);
  if (q1 != q2) return q1 < q2;
  return cross(a,b)>0;
}
// テ」ツδ凖」ツつッテ」ツδ暗」ツδォテ」ツ?ョテ・ツ崢榲ィツサツ「
P rotate(P p, double ang) {
  return p * P(cos(ang), sin(ang));
}
// テ・ツ篠淌ァツつケテ・ツ堕ィテ」ツつ甘」ツ?ョテァツ崢エテァツキツ堙」ツ?ョテ・ツ崢榲ィツサツ「
L rotate(L l, double ang) {
  return L(rotate(l[0], ang),rotate(l[1], ang));
}

int n;
P p[15];
int l[15];

void func(vector<G> &gs, P q[3]) {
  L m[3]; REP(i,3) m[i] = L(q[i],q[(i+1)%3]);
  if (cross(q[1]-q[0],q[2]-q[0]) < 0) {
    REP(i,3) swap(m[i][0],m[i][1]);
  }
  vector<G> res;
  
  FOR(it, gs) {
    REP(S,(1<<3)-1) {
      G r = *it;        
      REP(i,3) {
        L tmp = m[i];
        if (S>>i&1) swap(tmp[0],tmp[1]);
        r = convex_cut(r,tmp);
      }
      if (r.size() == 0 || area(r)<EPS) continue;
      // cout << "A " ;
      // FOR(it, r) cout << *it << " "; cout << endl;

      P g;
      FOR(it, r) g += *it;
      g /= r.size();
      // cout << g << " " << centroid(r) << endl;
      if (angle(q[0]-g,q[1]-g) < angle(q[0]-g,q[2]-g)) 
        res.push_back(r);
    }
  }
  gs = res;
}

int main() {
  while(cin >> n, n) {
    static int cs = 1;
    printf("Case %d: ", cs++);
    
    REP(i,n) cin >> p[i].real() >> p[i].imag();
    REP(i,n) {cin >> l[i];l[i]--;}
    if (n <= 3) {
      puts("Infinity");
      continue;
    }
    
    // const double INF = 1e6;
    P tmp[] = {P(INF,INF),P(-INF,INF),P(-INF,-INF),P(INF,-INF)};
    vector<G> gs;
    gs.push_back(G(tmp,tmp+4));
    
    REP(i,n) {
      P t[3] = {p[l[i]],p[l[(i+1)%n]],p[l[(i+2)%n]]};
      func(gs, t);
    }
    double ans = 0;
    FOR(it, gs) {
      // FOR(jt, *it) cout << *jt << " "; cout << endl;
      if (area(*it) < EPS) continue;
      P g;
      FOR(jt,*it) g += *jt;
      g /= it->size();
      // g = centroid(*it);
      bool ok = 1;
      for (int i=1; i<n-1; ++i) {
        if (angle(p[l[0]]-g,p[l[i]]-g) > angle(p[l[0]]-g,p[l[i+1]]-g)) {
          ok = 0;
          break;
        } 
      }
      if (ok) {
        // cout << g << " " << area(*it) <<  endl;        
        ans += area(*it);
      }
    }
    if (ans < EPS) {
      puts("No area"); 
    } else if (ans > 1e8) {
      puts("Infinity");
    } else {
      printf("%.10Lf\n", ans);
    }
  }
}
accuracy: 1
time_ms: 180
memory_kb: 1320
final_rank: 2

code_snippet: #include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <climits>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<(b)?(a=b,1):0)
#define chmin(a,b) (a>(b)?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)

#define double long double
typedef long long ll;
typedef pair<int,int> pii;
const int INF = 1e8;
const double PI = acos(-1);
const double EPS = 1e-8;
typedef complex<double> P;
namespace std {
  bool operator < (const P& a, const P& b) {
    // if (abs(a-b)<EPS) return 0;
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
  L() {}
};
ostream &operator<<(ostream &os, const L &a) {
  os << a[0] << " -> " << a[1];
  return os;
}

typedef vector<P> G;
#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
struct C {
  P p; double r;
  C(const P &p, double r) : p(p), r(r) { }
};

int ccw(P a, P b, P c) {
  b -= a; c -= a;
  if (cross(b, c) > EPS)   return +1;       // counter clockwise
  if (cross(b, c) < -EPS)   return -1;       // clockwise
  if (dot(b, c) < -EPS)     return +2;       // c--a--b on line
  if (norm(b) < norm(c)) return -2;       // a--b--c on line
  return 0;
}

bool intersectLL(const L &l, const L &m) {
  return abs(cross(l[1]-l[0], m[1]-m[0])) > EPS*10 || // non-parallel
         abs(cross(l[1]-l[0], m[0]-l[0])) < EPS;   // same line
}
bool intersectLS(const L &l, const L &s) {
  return cross(l[1]-l[0], s[0]-l[0])*       // s[0] is left of l
         cross(l[1]-l[0], s[1]-l[0]) < EPS; // s[1] is right of l
}
bool intersectLP(const L &l, const P &p) {
  return abs(cross(l[1]-p, l[0]-p)) < EPS;
}
bool intersectSS(const L &s, const L &t) {
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}
bool intersectSS2(const L &s, const L &t) { // テヲツ篠・テ」ツ?療」ツ?ヲテ」ツ??」ツつ凝」ツつ?」ツ?、テ」ツ?ッテ、ツコツ、テ・ツキツョテ」ツ?ィティツ?ε」ツ?暗」ツ?ェテ」ツ??
  REP(i, 2) {
    if (ccw(s[0], s[1], t[i]) == 0) {
      int c = ccw(s[0],s[1],t[!i]);
      if (s[0] == t[i]) {
        if (c!=-2&&c) return 0;
      } else if (s[1] == t[i]) {
        if (c!=2&&c) return 0;
      } else if (abs(c)==1) return 0;
    }
  }
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}
bool intersectSP(const L &s, const P &p) {
  return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality
}
bool intersectLH(const L &l, const L &h) {
  if (intersectLS(l,h)) return 1;
  if (!intersectLL(l,h)) return 0;
  if (abs(cross(l[1]-l[0],h[1]-h[0])) < EPS) return 1; // same line
  return (ccw(l[0],l[1],h[0]) == 1) ^ (cross(l[1]-l[0], h[1]-h[0]) > 0);
}
bool intersectHS(const L &h, const L &s) {
  if (intersectSS(h,s)) return 1;
  if (!intersectLS(h,s)) return 0;
  if (abs(cross(s[1]-s[0],h[1]-h[0])) < EPS) // same line
    return ccw(h[0],h[1],s[0]) != 2 || ccw(h[0],h[1],s[1]) != 2;
  return (ccw(s[0],s[1],h[0]) == 1) ^ (cross(s[1]-s[0], h[1]-h[0]) > 0);
}
bool intersectHH(const L &h, const L &k) {
  return intersectLH(h,k) && intersectLH(k,h);
}
bool intersectHS2(const L &h, const L &s) {
  L t(s); swap(t[0],t[1]);
  return intersectHH(h,s) && intersectHH(h,t);
}

P projection(const L &l, const P &p) {
  double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
  return l[0] + t*(l[0]-l[1]);
}
P reflection(const L &l, const P &p) {
  return p + P(2,0) * (projection(l, p) - p);
}
double distanceLP(const L &l, const P &p) {
  return abs(p - projection(l, p));
}
double distanceLL(const L &l, const L &m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m[0]);
}
double istanceLS(const L &l, const L &s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s[0]), distanceLP(l, s[1]));
}
double distanceSP(const L &s, const P &p) {
  const P r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s[0] - p), abs(s[1] - p));
}
double distanceSS(const L &s, const L &t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
             min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}
P crosspoint(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
  if (abs(A) < EPS) {
    cout << abs(A) << endl;
    cout << intersectLL(l,m) << endl;
    cout << l << " " << m << endl;
  }
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}
bool intersectLHL(const L &l, const L &m) {
  if (!intersectLL(l,m)) return 0;
  P cp = crosspoint(l,m);
  if (ccw(m[0],m[1],cp) == 2) return 0;
  return 1;
}
bool intersectHLS(const L &l, const L &s) {
  if (!intersectLS(l,s)) return 0;
  P cp = crosspoint(l,s);
  if (ccw(l[0],l[1],cp) == 2) return 0;
  return 1;
}
double area(const G& g) {
  double A = 0;
  for (int i = 0; i < g.size(); ++i) {
    A += cross(g[i], next(g, i));
  }
  return abs(A/2);
}

G convex_cut(const G& g, const L& l) {
  G Q;
  REP(i, g.size()) {
    P A = curr(g, i), B = next(g, i);
    if (ccw(l[0], l[1], A) != -1) Q.push_back(A);
    if (ccw(l[0], l[1], A)*ccw(l[0], l[1], B) < -EPS)
      if (abs(cross(l[1]-l[0],B-A)) > EPS)
        Q.push_back(crosspoint(L(A, B), l));
  }
  return Q;
}
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

// テ、ツクツ?ヲツァツ佚」ツ?ェテ・ツ、ツ堙ィツァツ津・ツスツ「テ」ツ?ョテゥツ?催・ツソツ?
P centroid(const vector<P> &v) {
  double S = 0;
  P res;
  REP(i,v.size()) {
    int j = i+1;
    if (j == v.size()) j = 0;
    double tmp = cross(v[i], v[j]);
    S += tmp;
    res += (v[i] + v[j]) * tmp;
  }
  S /= 2;
  res /= 6*S;
  return res;
}

double manDistanceSP(const L &l, const P &p) {
  double res = INF;
  L xl = L(p, p + P(1,0));
  if (intersectLS(xl, l)){
    P cp = crosspoint(xl, l);
    double d = abs(p-cp);
    res = min(res, d);
  }
  L yl = L(p, p + P(0,1));
  if (intersectLS(yl, l)) {
    P cp = crosspoint(yl, l);
    double d = abs(p-cp);
    res = min(res, d);
  }
  res = min(res, abs(l[0].real()-p.real()) + abs(l[0].imag()-p.imag()));
  res = min(res, abs(l[1].real()-p.real()) + abs(l[1].imag()-p.imag()));
  return res;
}

// テァツつケ-テ・ツ?クテ・ツ、ツ堙ィツァツ津・ツスツ「テ・ツ個?・ツ青ォテゥツ鳴「テ、ツソツ?
bool convex_contain(const G &g, const P &p) { // テ・ツ債甘ヲツ卍づィツィツ暗・ツ崢榲」ツつ甘」ツつ津、ツサツョテ・ツョツ?
  REP(i,g.size())
    if (ccw(g[i], next(g, i), p) == -1) return 0;
  return 1;
}
// テ・ツ?クテ・ツ、ツ堙ィツァツ津・ツスツ「テ・ツ青古・ツ」ツォテ」ツ?ョテゥツ?催」ツ?ェテ」ツつ甘・ツ按、テ・ツョツ?
bool intersectGG(const G &g1, const G &g2) {
  if (convex_contain(g1, g2[0])) return 1;
  if (convex_contain(g2, g1[0])) return 1;
  REP(i,g1.size()) REP(j,g2.size()) {
    if (intersectSS(L(g1[i], next(g1, i)), L(g2[j], next(g2, j)))) return 1;
  }
  return 0;
}
// テ・ツ?クテ・ツ、ツ堙ィツァツ津・ツスツ「テ」ツ?ィテァツつケテ」ツ?ョティツキツ敕ゥツ崢「
double distanceGP(const G &g, const P &p) {
  if (convex_contain(g, p)) return 0;
  double res = INF;
  REP(i, g.size()) {
    res = min(res, distanceSP(L(g[i], next(g, i)), p));
  }
  return res;
}
// テ・ツ楪づァツ崢エテ、ツコツ古ァツュツ嘉・ツ按?ァツキツ?
L bisector(const P &a, const P &b) {
  P A = (a+b)*P(0.5,0);
  return L(A, A+(b-a)*P(0, PI/2));
}
// テ」ツδ愿」ツδュテ」ツδ偲」ツつ、テゥツ?佚・ツ淞?
G voronoi_cell(G g, const vector<P> &v, int s) {
  REP(i, v.size())
    if (i!=s)
      g = convex_cut(g, bisector(v[s], v[i]));
  return g;
}
// ティツァツ津・ツコツヲテゥツ鳴「テゥツ?」
double angle(const P &a, const P &b) {        // テ」ツδ凖」ツつッテ」ツδ暗」ツδォテッツスツ?」ツ?凝」ツつ嘉」ツ?ソテ」ツ?淌」ツδ凖」ツつッテ」ツδ暗」ツδォテッツスツづ」ツ?ョティツァツ津・ツコツヲテ」ツ?ョティツィツ暗ァツョツ夕0,2pi)
  double ret = arg(b)-arg(a);
  return (ret>=0) ? ret : ret + 2*PI;
}
double angle2(const P &a, const P &b) { // テ」ツδ凖」ツつッテ」ツδ暗」ツδォaテ」ツ?ィテ」ツδ凖」ツつッテ」ツδ暗」ツδォbテ」ツ?ョテゥツ鳴禿」ツ?ョティツァツ津・ツコツヲ
  return min(angle(a,b), angle(b,a));
}
double rtod(double rad) {       // テ」ツδゥテ」ツつクテ」ツつ「テ」ツδウテ「ツ?津・ツコツヲ
  return rad*180/PI;
}
double dtor(double deg) {       // テ・ツコツヲテ「ツ?津」ツδゥテ」ツつクテ」ツつ「テ」ツδウ
  return deg*PI/180;
}
int quadrant(const P &a) {      // テヲツ卍づィツィツ暗・ツ崢榲」ツつ甘・ツ?エテ」ツ?ッテ・ツ青ォテ」ツ?ソテ」ツ??・ツ債甘ヲツ卍づィツィツ暗・ツ崢榲」ツつ甘・ツ?エテ」ツ?ッテ・ツ青ォテ」ツ?セテ」ツ?ェテ」ツ??
  if (a.real() > 0 && a.imag() >= 0) return 0;
  if (a.real() <= 0 && a.imag() > 0) return 1;
  if (a.real() < 0 && a.imag() <= 0) return 2;
  return 3;
}
bool cmpAngle(const P &a, const P&b) { // テ」ツδュテ」ツδ静」ツつケテ」ツδ暗」ツ?ェティツァツ津・ツコツヲテヲツッツ氾ィツシツ?
  int q1 = quadrant(a);
  int q2 = quadrant(b);
  if (q1 != q2) return q1 < q2;
  return cross(a,b)>0;
}
// テ」ツδ凖」ツつッテ」ツδ暗」ツδォテ」ツ?ョテ・ツ崢榲ィツサツ「
P rotate(P p, double ang) {
  return p * P(cos(ang), sin(ang));
}
// テ・ツ篠淌ァツつケテ・ツ堕ィテ」ツつ甘」ツ?ョテァツ崢エテァツキツ堙」ツ?ョテ・ツ崢榲ィツサツ「
L rotate(L l, double ang) {
  return L(rotate(l[0], ang),rotate(l[1], ang));
}

int n;
P p[15];
int l[15];

void func(vector<G> &gs, P q[3]) {
  L m[3]; REP(i,3) m[i] = L(q[i],q[(i+1)%3]);
  if (cross(q[1]-q[0],q[2]-q[0]) < 0) {
    REP(i,3) swap(m[i][0],m[i][1]);
  }
  vector<G> res;
  
  FOR(it, gs) {
    REP(S,(1<<3)-1) {
      G r = *it;        
      REP(i,3) {
        L tmp = m[i];
        if (S>>i&1) swap(tmp[0],tmp[1]);
        r = convex_cut(r,tmp);
      }
      if (r.size() == 0 || area(r)<EPS) continue;
      // cout << "A " ;
      // FOR(it, r) cout << *it << " "; cout << endl;

      P g;
      FOR(it, r) g += *it;
      g /= r.size();
      // cout << g << " " << centroid(r) << endl;
      if (angle(q[0]-g,q[1]-g) < angle(q[0]-g,q[2]-g)) 
        res.push_back(r);
    }
  }
  gs = res;
}

int main() {
  while(cin >> n, n) {
    static int cs = 1;
    printf("Case %d: ", cs++);
    
    REP(i,n) cin >> p[i].real() >> p[i].imag();
    REP(i,n) {cin >> l[i];l[i]--;}
    if (n <= 3) {
      puts("Infinity");
      continue;
    }
    
    // const double INF = 1e6;
    P tmp[] = {P(INF,INF),P(-INF,INF),P(-INF,-INF),P(INF,-INF)};
    vector<G> gs;
    gs.push_back(G(tmp,tmp+4));
    
    REP(i,n) {
      P t[3] = {p[l[i]],p[l[(i+1)%n]],p[l[(i+2)%n]]};
      func(gs, t);
    }
    double ans = 0;
    FOR(it, gs) {
      // FOR(jt, *it) cout << *jt << " "; cout << endl;
      if (area(*it) < EPS) continue;
      P g;
      FOR(jt,*it) g += *jt;
      g /= it->size();
      // g = centroid(*it);
      bool ok = 1;
      for (int i=1; i<n-1; ++i) {
        if (angle(p[l[0]]-g,p[l[i]]-g) > angle(p[l[0]]-g,p[l[i+1]]-g)) {
          ok = 0;
          break;
        } 
      }
      if (ok) {
        // cout << g << " " << area(*it) <<  endl;        
        ans += area(*it);
      }
    }
    if (ans < EPS) {
      puts("No area"); 
    } else if (ans > 1e8) {
      puts("Infinity");
    } else {
      printf("%.10Lf\n", ans);
    }
  }
}
accuracy: 1
time_ms: 220
memory_kb: 1320
final_rank: 3

code_snippet: #include<cmath>
#include<cstdio>
#include<vector>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const long double EPS=1e-8;
const long double PI=acos(-1);

struct point{
	long double x,y;
	point():x(0),y(0){}
	point(long double x,long double y):x(x),y(y){}
	point &operator/=(double c){ x/=c; y/=c; return *this; }
	point operator+(const point &a)const{ return point(x+a.x,y+a.y); }
	point operator-(const point &a)const{ return point(x-a.x,y-a.y); }
	bool operator< (const point &a)const{ return x+EPS<a.x || abs(x-a.x)<EPS && y+EPS<a.y; }
	bool operator==(const point &a)const{ return abs(x-a.x)<EPS && abs(y-a.y)<EPS; }
};

point operator*(long double c,const point &a){ return point(c*a.x,c*a.y); }

long double cross(const point &a,const point &b){ return a.x*b.y-a.y*b.x; }

long double arg(const point &a){
	long double t=atan2(a.y,a.x);
	return t<0?t+2*PI:t;
}

struct line{
	point a,b;
	line(){}
	line(const point &a,const point &b):a(a),b(b){}
};

typedef vector<point> polygon;

enum{CCW=1,CW=-1,ON=0};
int ccw(const point &a,const point &b,const point &c){
	long double rdir=cross(b-a,c-a);
	if(rdir> EPS) return CCW;
	if(rdir<-EPS) return CW;
	return ON;
}

long double area(const polygon &F){
	int n=F.size();
	long double a=0;
	rep(i,n) a+=cross(F[i],F[(i+1)%n]);
	return abs(a)/2;
}

bool intersect(const line &L1,const line &L2){
	return abs(cross(L1.b-L1.a,L2.b-L2.a))>EPS
		|| abs(cross(L1.b-L1.a,L2.a-L1.a))<EPS;
}

point get_intersect(const line &L1,const line &L2){
	long double a1=cross(L1.b-L1.a,L2.b-L2.a);
	long double a2=cross(L1.b-L1.a,L1.b-L2.a);
	if(abs(a1)<EPS) return L1.a;
	return L2.a+a2/a1*(L2.b-L2.a);
}

polygon convex_cut(const polygon &F,const line &L){
	int n=F.size();
	polygon G;
	rep(i,n){
		int d1=ccw(L.a,L.b,F[i]);
		int d2=ccw(L.a,L.b,F[(i+1)%n]);
		if(d1!=CW) G.push_back(F[i]);
		if(d1==CCW && d2==CW || d1==CW && d2==CCW){
			G.push_back(get_intersect(L,line(F[i],F[(i+1)%n])));
		}
	}
	return G;
}

point centroid(const polygon &F){
	int n=F.size();
	point g;
	rep(i,n){
		g.x+=(F[i].x+F[(i+1)%n].x)*cross(F[i],F[(i+1)%n]);
		g.y+=(F[i].y+F[(i+1)%n].y)*cross(F[i],F[(i+1)%n]);
	}
	g/=6*area(F);
	return g;
}

bool is_cyclic_same(int n,const int *order,const int *order2){
	rep(i,n) if(order2[i]==order[0]) {
		rep(j,n) if(order[j]!=order2[(i+j)%n]) return false;
	}
	return true;
}

int main(){
	for(int cas=1,n;scanf("%d",&n),n;cas++){
		point P[10];
		rep(i,n) scanf("%Lf%Lf",&P[i].x,&P[i].y);

		int order[10];
		rep(i,n) scanf("%d",order+i), order[i]--;

		long double ans=0;
		rep(S,1<<n){
			polygon F(4);
			F[0]=point(-1e7,-1e7);
			F[1]=point( 1e7,-1e7);
			F[2]=point( 1e7, 1e7);
			F[3]=point(-1e7, 1e7);
			rep(i,n){
				line L(P[order[i]],P[order[(i+1)%n]]);
				if(S>>i&1) swap(L.a,L.b);
				F=convex_cut(F,L);
			}

			point g=centroid(F);
			pair<double,int> tmp[10];
			rep(i,n) tmp[i]=make_pair(arg(P[i]-g),i);
			sort(tmp,tmp+n);

			int order2[10];
			rep(i,n) order2[i]=tmp[i].second;

			if(is_cyclic_same(n,order,order2)) ans+=area(F);
		}

		printf("Case %d: ",cas);
		if     (ans<EPS) puts("No area");
		else if(ans>1e7) puts("Infinity");
		else             printf("%.9Lf\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 1128
final_rank: 1